使用spring-data-couchbase,我想用通用JSON定义一个具有字段settings
的文档。为此,我创建了一个类
@Document
public class SampleDoc {
@Id
@NotNull
protected String id;
@Field
private JsonNode settings;
}
当我尝试将JSON对象持久化到此文档实例
{
"someField" : "someData"
}
在CouchBase中作为
保存"settings": {
"_children": {
"someField": {
"type": "com.fasterxml.jackson.databind.node.TextNode",
"_value": "someData"
}
},
"type": "com.fasterxml.jackson.databind.node.ObjectNode",
"_nodeFactory": {
"_cfgBigDecimalExact": false
}
}
当我试图通过CouchbaseRepository.findById
从数据库获取文档时,它返回错误:
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.data.mapping.model.MappingInstantiationException: Failed to instantiate com.fasterxml.jackson.databind.node.ObjectNode using constructor NO_CONSTRUCTOR with arguments ] with root cause
我如何将通用JSON对象持久化到Couchbase并确保它被存储为简单的JSON,如:
{
//other fields
"settings" : {
"someField" : "someData"
}
//other fields
}
谢谢
编辑:下面提到的转换器现在包含在Spring Data Couchbase中。
您可以像这样创建两个转换器。
然后通过覆盖AbstractCouchbaseConfiguration中的customConversions()方法将它们添加为CustomConverters。与原来相比,唯一的变化是增加了两个转换器。
我打开了一个问题https://github.com/spring-projects/spring-data-couchbase/issues/1650
@WritingConverter
public enum JsonNodeToMap implements Converter<JsonNode, CouchbaseDocument> {
INSTANCE;
@Override
public CouchbaseDocument convert(JsonNode source) {
if( source == null ){
return null;
}
return new CouchbaseDocument().setContent(JsonObject.fromJson(source.toString()));
}
}
@ReadingConverter
public enum MapToJsonNode implements Converter<CouchbaseDocument, JsonNode> {
INSTANCE;
static ObjectMapper mapper= new ObjectMapper();
@Override
public JsonNode convert(CouchbaseDocument source) {
if( source == null ){
return null;
}
return mapper.valueToTree(source.export());
}
}
------------------------------------------------------
public CustomConversions customConversions(CryptoManager cryptoManager, ObjectMapper objectMapper) {
List<GenericConverter> newConverters = new ArrayList();
CustomConversions customConversions = CouchbaseCustomConversions.create(configurationAdapter -> {
SimplePropertyValueConversions valueConversions = new SimplePropertyValueConversions();
valueConversions.setConverterFactory(
new CouchbasePropertyValueConverterFactory(cryptoManager, annotationToConverterMap(), objectMapper));
valueConversions.setValueConverterRegistry(new PropertyValueConverterRegistrar().buildRegistry());
valueConversions.afterPropertiesSet(); // wraps the CouchbasePropertyValueConverterFactory with CachingPVCFactory
configurationAdapter.setPropertyValueConversions(valueConversions);
configurationAdapter.registerConverters(newConverters);
configurationAdapter.registerConverter(OtherConverters.JsonNodeToMap.INSTANCE); // added
configurationAdapter.registerConverter(OtherConverters.MapToJsonNode.INSTANCE); // added
configurationAdapter.registerConverter(new OtherConverters.EnumToObject(getObjectMapper()));
configurationAdapter.registerConverterFactory(new IntegerToEnumConverterFactory(getObjectMapper()));
configurationAdapter.registerConverterFactory(new StringToEnumConverterFactory(getObjectMapper()));
configurationAdapter.registerConverterFactory(new BooleanToEnumConverterFactory(getObjectMapper()));
});
return customConversions;
}