Встраивание JsonNode Джексона в POJO, хранящийся в CrudRepository

Вот где я. У меня есть метод контроллера MVC, который принимает содержимое JSON. Поскольку мне нужно проверить его с помощью схемы JSON, мой контроллер отображает тело запроса как 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 ответ

Это не работает таким образом, потому что соглашения о сериализации и десериализации уже установлены. Вы можете переопределить эти соглашения с помощью пользовательской сериализации и десериализации в Джексоне, но это может выйти за рамки "грубого" подхода, который вы ищете.

Я вижу, вы хотите, чтобы один подход подошел ко всему подходу к моделированию данных.

Могу ли я рекомендовать хранить карту

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

Я надеюсь это имеет смысл.

Другие вопросы по тегам