I've made my research, and you can do it by implementing your own Custom Converters (as specified here: https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mongo.custom-converters)
The solution is:
- Create your specific converters, one for the reader, the other for the writer
import org.bson.Document;
import org.springframework.core.convert.converter.Converter;
import java.util.HashMap;
import java.util.Map;
public class ContactReadConverter implements Converter<Document, Contact> {
@Override
public Contact convert(Document source) {
Contact c = new Contact();
c.setId((Long) source.get("_id"));
Map<String, String> props = new HashMap<>();
source.keySet().stream()
.filter(key -> !key.equals("_id"))
.forEach(key -> props.put(key, (String) source.get(key)));
c.setProperties(props);
return c;
}
}
import org.bson.Document;
import org.springframework.core.convert.converter.Converter;
public class ContactWriteConverter implements Converter<Contact, Document> {
@Override
public Document convert(Contact source) {
Document dbo = new Document();
dbo.put("_id", source.getId());
source.getProperties()
.forEach(dbo::put);
return dbo;
}
}
- Then, you need to add those converters into MongoDB. Here is how I did:
@SpringBootApplication
public class MainClass {
...
@Bean
public MongoCustomConversions customConversions() {
List<Converter<?, ?>> converterList = new ArrayList<>();
converterList.add(new ContactReadConverter());
converterList.add(new ContactWriteConverter());
return new MongoCustomConversions(converterList);
}
}
And my Contact
class, just in case:
import org.springframework.data.mongodb.core.mapping.Document;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.util.Map;
@Document
public class Contact {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private Map<String, String> properties;
public Contact() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Map<String, String> getProperties() {
return properties;
}
public void setProperties(Map<String, String> properties) {
this.properties = properties;
}
@Override
public String toString() {
return "Contact{" +
"id=" + id +
", properties=" + properties +
'}';
}
}
And my result is:
{ "_id" : NumberLong(0), "toto" : "titi", "tata" : "tonton" }
Things to consider:
- Customize for your need. Because with the solutions provided, you will interpret every other field you might have and store it to your Map. Which is not so great...
- Be careful, I hope there is no impact on the "basic" mongo configuration with default converter.