Перетворити JsonNode в POJO


143

Це може здатися трохи незвичним, але я шукаю ефективний спосіб перетворити / перетворити 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до своєї Моделі

Відповіді:


264

У Jackson 2.4 ви можете конвертувати наступне:

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

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


У старих версіях Джексона це було б

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

19
На жаль, немає дереваToValue (TreeNode n, TypeReference <T>) варіант, як це є для readValue (). Погана новина для тих, хто має справу із більш складними типами із дженериками :(
Espinosa

13
@Espinosa За jackson-databind # 1294 , ви захочете чогось на кшталт (на жаль, більш багатослівного)jsonObjectMapper.readValue(jsonObjectMapper.treeAsTokens(someJsonNode), someTypeReference)
М. Джастін

Для старшої версії використовуйте:objectMapper.treeToValue(jsonNode, MyClass.class)
amod

2
Ви також можете використовувати цей метод у StdDeserializer : p.codec.treeToValue.
galcyurio

@icedtrees jsonObjectMapper - це примірник JsonObjectMapper або просто ObjectMapper
KNDheeraj

8

Для цього слід зробити фокус:

mapper.readValue(fileReader, MyClass.class);

Я говорю, що слід, тому що я використовую це з a String, не a, 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/JacksonHowToCustomDeserializer

Редагувати: Я просто згадав щось інше. Якщо ваш об’єкт, що входить, має більше властивостей, ніж у POJOнього, і ви просто хочете ігнорувати додаткові дані, ви хочете встановити це:

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

Або ви отримаєте помилку, яка не може знайти властивість встановити.


Я буду використовувати CustomDeserializer, це позбавить мене від багатьох головних болів! Я також зможу застосувати мої стратегії версій із дуже невеликими модифікаціями. Дякую!
Олександр

5
Синтаксис тепер: com.fasterxml.jackson.databind.ObjectMapper mapper = новий com.fasterxml.jackson.databind.ObjectMapper (); mapper.disable (com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
llambda

Гарна точка @llambda! Я не торкнувся ObjectMapper з версії 1.7.9, схоже, моя відповідь застаріла кількома версіями. Однозначно перевірте, яку версію Jackson ви використовуєте.
Ерік Барр

@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

Зараз документація знаходиться на веб-
Девід Тонхофер

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);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.