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

时间:2014-07-21 03:51:54

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

这是我在的地方。我有一个接受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 :(得分:0)

它不起作用,因为已经建立了序列化和反序列化约定。您可以使用自定义序列化&amp ;;覆盖这些约定。杰克逊的反序列化 - 但这可能超出了你正在寻找的“原始”方法。

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

我建议存储地图

@Field
private Map<String, String> data;

这张地图是私密的,所以它很完美。

然后你可以有两种方法

一种方法就像这样放入地图

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

}

另一个像地图一样从地图中获取

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进行序列化/反序列化的内容。

我希望这是有道理的。