Встраивание 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.
Я надеюсь это имеет смысл.