Преобразование JsonNode в POJO

149

Это может показаться немного необычным, но я ищу эффективный способ преобразовать / сопоставить a JsonNodeв POJO.

Я храню часть информации о моей модели в файлах json, и мне нужно поддерживать несколько версий моей модели.

Что я делаю, так это загружаю файл json в память в JsonNode, применяю несколько стратегий управления версиями, чтобы он соответствовал последней версии моей модели.

    ObjectMapper mapper = new ObjectMapper();
    BufferedReader fileReader = new BufferedReader(new FileReader(projPath));

    JsonNode rootNode = mapper.readTree(fileReader);

    //Upgrade our file in memory
    applyVersioningStrategy(rootNode);

    ProjectModel project = mapJsonNodeToProject(rootNode);

Если нет более быстрого способа сделать это, я, вероятно, закончу просто вручную, применив JsonNodesк моей модели

Александр
источник

Ответы:

275

В Jackson 2.4 вы можете конвертировать следующим образом:

MyClass newJsonNode = jsonObjectMapper.treeToValue(someJsonNode, MyClass.class);

где jsonObjectMapperДжексон ObjectMapper.


В более старых версиях Джексона это было бы

MyClass newJsonNode = jsonObjectMapper.readValue(someJsonNode, MyClass.class);
ледовые деревья
источник
20
К сожалению, нет варианта treeToValue (TreeNode n, TypeReference <T> type), как для readValue (). Плохая новость для тех, кто имеет дело с более сложными типами с помощью дженериков :(
Espinosa
13
@Espinosa Per jackson -databind # 1294 , вам нужно что-то вроде (к сожалению, более подробного)jsonObjectMapper.readValue(jsonObjectMapper.treeAsTokens(someJsonNode), someTypeReference)
M. Justin
Для более старой версии используйте:objectMapper.treeToValue(jsonNode, MyClass.class)
amod
2
Вы также можете использовать этот метод в StdDeserializer: p.codec.treeToValue.
galcyurio
@icedtrees jsonObjectMapper - это экземпляр JsonObjectMapper или просто
ObjectMapper
8

Это должно помочь:

mapper.readValue(fileReader, MyClass.class);

Я говорю «должен», потому что я использую это с, а Stringне с, BufferedReaderно он все равно должен работать.

Вот мой код:

String inputString = // I grab my string here
MySessionClass sessionObject;
try {
    ObjectMapper objectMapper = new ObjectMapper();
    sessionObject = objectMapper.readValue(inputString, MySessionClass.class);

Вот официальная документация для этого вызова: http://jackson.codehaus.org/1.7.9/javadoc/org/codehaus/jackson/map/ObjectMapper.html#readValue(java.lang.String, java.lang.Class)

Вы также можете определить собственный десериализатор при создании экземпляра ObjectMapper: http://wiki.fasterxml.com/JacksonHowToCustomDeserializers

Изменить: я только что вспомнил кое-что еще. Если ваш входящий объект имеет больше свойств, чем POJOимеет, и вы просто хотите игнорировать дополнительные функции, вы захотите установить это:

    objectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);

Или вы получите сообщение об ошибке, что не удается найти свойство, в которое нужно установить.

Эрик Барр
источник
Я буду использовать CustomDeserializers, это избавит меня от многих головных болей! Я также смогу применить там свои стратегии управления версиями с очень небольшими изменениями. Благодарность!
Александр
5
Теперь синтаксис: com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper (); mapper.disable (com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
llambda
Хороший момент @llambda! Я не трогал ObjectMapper с версии 1.7.9, похоже, мой ответ устарел на несколько версий. Обязательно проверьте, какую версию Джексона вы используете.
Эрик Барр
@EricBarr, я использую Jackson v1.9.11, и синтаксис в вашем ответе правильный для этой версии. Возможно, они пытались что-то изменить и снова вернули их в более новых версиях
Ивайло Славов
5

Если вы используете org.codehaus.jackson, это стало возможно с версии 1.6. Вы можете преобразовать JsonNode в POJO с помощью ObjectMapper#readValue: http://jackson.codehaus.org/1.9.4/javadoc/org/codehaus/jackson/map/ObjectMapper.html#readValue(org.codehaus.jackson.JsonNode , java. lang.Class)


    ObjectMapper mapper = new ObjectMapper();
    JsonParser jsonParser = mapper.getJsonFactory().createJsonParser("{\"foo\":\"bar\"}");
    JsonNode tree = jsonParser.readValueAsTree();
    // Do stuff to the tree
    mapper.readValue(tree, Foo.class);
мамра
источник
5
Эти методы, кажется, отсутствуют в 2.4.4
Кевин Виттек
1
См icedtrees' ответ ниже, для решения версии 2
Тим Buthe
Документация теперь находится по адресу быстрееxml.github.io
jackson-
3
String jsonInput = "{ \"hi\": \"Assume this is the JSON\"} ";
com.fasterxml.jackson.databind.ObjectMapper mapper =
    new com.fasterxml.jackson.databind.ObjectMapper();
MyClass myObject = objectMapper.readValue(jsonInput, MyClass.class);

Если ваш вход JSON имеет больше свойств, чем ваш POJO, и вы просто хотите игнорировать дополнительные функции в Jackson 2.4, вы можете настроить свой ObjectMapper следующим образом. Этот синтаксис отличается от более старых версий Джексона. (Если вы используете неправильный синтаксис, он ничего не сделает.)

mapper.disable(com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNK‌​NOWN_PROPERTIES);
лямбда
источник