首页 文章

在存储在CrudRepository中的POJO中嵌入Jackson JsonNode

提问于
浏览
1

这就是我在的地方 . 我有一个接受JSON内容的MVC控制器方法 . 因为我需要使用JSON Schema验证它,我的控制器将请求体映射为Jackson JsonNode .

验证成功后,我需要将数据保存在Spring Couchbase存储库中 . 请考虑以下代码段:

public class Foo
{
    @Id
    private String  _id;

    @Version
    private Long    _rev;

    @Field
    private JsonNode nodeData;

    // .. Other data and members.
}


//
// Repository
//

@Repository
public interface FooRepository extends CrudRepository<Foo, String> {
}

当我将这些元素存储到Couch存储库中时,我希望看到的是这样的:

{
  "_class": "Foo",
  "field1": "field 1 data",
  "nodeData"  : {
    "Some" : "additional data",
    "from"  : "JsonNode"
  }
}

相反,我在存储库中看到的是这样的:

{
  "_class": "Foo",
  "field1": "field 1 data",
  "nodeData"  : {
    "_children": {
      "Some": {
        "_value": "additional data",
        "_class": "com.fasterxml.jackson.databind.node.TextNode"
      },
      "From": {
        "_value": "jsonNode",
        "_class": "com.fasterxml.jackson.databind.node.TextNode"
      },
    "_nodeFactory": {
      "_cfgBigDecimalExact": false
    }
  }
}

JsonNode的每个存储属性都使用类信息和其他元数据进行修饰,这是不可取的 .

我的问题 - 是否有一种首选的方式让CrudRepository以我希望的方式运行?

1 回答

  • 0

    它不起作用,因为已经 Build 了序列化和反序列化约定 . 您可以在Jackson中使用自定义序列化和反序列化来覆盖这些约定 - 但这可能超出了您正在寻找的“原始”方法 .

    我看到你想要一种适合所有数据建模方法的鞋子 .

    我可能建议存储 Map

    @Field
    private Map<String, String> data;
    

    这张 Map 是私人的,所以它很完美 .

    然后,您可以有两种方法

    一种方法就像这样放到 Map 上

    ObjectMapper mapper = new ObjectMapper()
    
    public void setFeild(String name, Object value) {
    
        ObjectNode node new ObjectNode(JsonNodeFactory.instance);
        node.put("clazz", value.getClass().getName());
        if (value instance of String) {
            node.put("value", value)
        } else {
            node.put("value", mapper.writeValueAsString(data));
        }
        data.put(name, node.toString());
    
    }
    

    另一个像这样从 Map 中获取

    public Object getField(String name) {
    
         if (data.contains(name)) {
             JsonNode node = mapper.readValue(data.get(name), JsonNode.class);
             Class clazz = Class.forName(node.get("class").textValue());
             if (clazz.equals(String.class) {
                 return node.get("value").textValue();
             } else {
                  return (Object) mapper.readValue(node.get("value"), clazz);
             }
         }
    
    }
    

    您应该更新此实现以处理Date,Integer,Boolean,Double ...等我处理String的方式相同 - POJO是您对json进行序列化/反序列化的内容 .

    我希望这是有道理的 .

相关问题