【问题标题】:Upsert Document with a generic json field使用通用 json 字段更新插入文档
【发布时间】:2023-01-24 07:19:52
【问题描述】:

使用 spring-data-couchbase 我想定义一个带有字段 settings 和通用 JSON 的文档。为此,我创建了一个类

@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
}

谢谢

【问题讨论】:

    标签: java json spring-data couchbase spring-data-couchbase


    【解决方案1】:

    您可以像这样创建两个转换器:

    ** @WritingConverter 公共枚举 JsonNodeToMap 实现 Converter<JsonNode, CouchbaseDocument> { 实例;

        @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());
        }
    }
    

    **

    然后通过覆盖 AbstractCouchbaseConfiguration 中的 customConversions() 方法将它们添加为 CustomConverters。与原来的唯一变化是添加了两个转换器。

    ** 公共 CustomConversions customConversions(CryptoManager cryptoManager,ObjectMapper objectMapper){ 列表 newConverters = new ArrayList(); CustomConversions customConversions = CouchbaseCustomConversions.create(configurationAdapter -> { SimplePropertyValueConversions valueConversions = new SimplePropertyValueConversions(); valueConversions.setConverterFactory( 新 CouchbasePropertyValueConverterFactory(cryptoManager,annotationToConverterMap(),objectMapper)); valueConversions.setValueConverterRegistry(new PropertyValueConverterRegistrar().buildRegistry()); valueConversions.afterPropertiesSet(); // 用 CachingPVCFactory 包装 CouchbasePropertyValueConverterFactory 配置适配器.setPropertyValueConversions(valueConversions); 配置适配器.registerConverters(newConverters); 配置适配器.registerConverter(OtherConverters.JsonNodeToMap.INSTANCE); 配置适配器.registerConverter(OtherConverters.MapToJsonNode.INSTANCE); configurationAdapter.registerConverter(new OtherConverters.EnumToObject(getObjectMapper())); 配置适配器.registerConverterFactory(new IntegerToEnumConverterFactory(getObjectMapper())); 配置适配器.registerConverterFactory(new StringToEnumConverterFactory(getObjectMapper())); 配置适配器.registerConverterFactory(new BooleanToEnumConverterFactory(getObjectMapper())); }); 返回自定义转化; } **

    【讨论】:

      猜你喜欢
      • 2023-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-23
      • 1970-01-01
      • 1970-01-01
      • 2020-02-07
      • 1970-01-01
      相关资源
      最近更新 更多