2015-01-18 4 views
1

Это ответ json, возвращаемый API MediaWiki. Я хочу создать класс, чтобы иметь возможность десериализовать его, используя библиотеку Джексона. Проблема в том, что этот json содержит ключ, который отличается от каждого запроса (здесь 290).Как десериализовать этот json

{ 
    "query-continue": { 
     "revisions": { 
      "rvcontinue": 633308090 
     } 
    }, 
    "query": { 
     "pages": { 
      "290": { 
       "pageid": 290, 
       "ns": 0, 
       "title": "A", 
       "revisions": [ 
        { 
         "user": "Mr. Guye", 
         "timestamp": "2014-12-07T17:45:55Z", 
         "comment": "comment", 
         "contentformat": "text/x-wiki", 
         "contentmodel": "wikitext", 
         "*": "content" 
        } 
       ] 
      } 
     } 
    } 
} 

Как создать класс (или сконфигурировать картограф) для десериализации этого json?

+0

Сначала получите ключи, а затем найдите эти ключи во втором проходе. Каждый раз, когда вы углубляетесь, и есть ключ, его другой проход, пока не будет никаких ключей. Таким образом, вы создадите массив ключей –

ответ

-1

Это похоже на пару ключевых значений. Вы можете использовать карту, чтобы десериализации пары ключ-значение:

public class Query { 

    private Map<Integer, Page> pages; 

    public Map<Integer, Page> getPages() { 
     return pages; 
    } 

    public void setPages(Map<Integer, Page> pages) { 
     this.pages = pages; 
    } 
} 

Джексон обрабатывает такие десериализации по умолчанию.

0

Короткий ответ: вы не можете, по крайней мере, не в текущем формате с присутствующей этой гнусной звездочкой. Поэтому мы должны будем использовать немного хакеров здесь, чтобы выполнить эту работу, и я предупреждаю вас заранее, что это будет не так.

Во-первых, скопируйте этот ответ, затем перейдите к http://www.jsonschema2pojo.org/ и вставьте его в текстовое поле JSON. Вставив его, измените звездочку на нечто более цивилизованное, например «контент». Выберите JSON (по умолчанию JSON Schema) для типа источника, введите свой пакет и имя корневого класса соответственно и нажмите JAR, чтобы сгенерировать пакет со всеми POJO, которые соответствуют этой JSON. Вы также можете нажать «Предварительный просмотр» и скопировать код в исходные файлы - это действительно зависит от вас. .

Теперь, когда мы имеем действительную версию этой JSON структуры, мы используем Джексон, чтобы прочитать его в случае, если ваш JSON строка называется jsonResponse и соответствующий класс POJO является MediaWiki, то преобразовать его с Джексоном, как это:

ObjectMapper objectMapper = new ObjectMapper(); 
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 
MediaWiki mw = objectMapper.readValue(profileJson, MediaWiki.class); 

Ключевым здесь является FAIL_ON_UNKNOWN_PROPERTIES, установленное на false, что означает, что он будет игнорировать эту звездочку и создать для вас все остальное.

Теперь, чтобы на самом деле захватить любое значение для этой звездочки и сохранить его в нашем атрибуте «content» (или что бы вы хотели заменить звездочкой), вам придется проанализировать эту присоску на стороне клиента и передать его в качестве отдельного входного параметра, и чтобы сделать это, вам придется дергать его по телефону что-то вроде этого:

var content = query.pages.290.revisions["*"]; 

Этот параметр содержимое передается и сохраняется его в атрибут содержимого вашего Pojo в.

Я знаю, что это большая работа, и если у кого-то еще есть более элегантное решение, поделитесь им. Как я уже сказал, моя не будет красивой. :-)

+1

Asterisk не проблема. Может быть легко проанализирован с помощью аннотации Jackson json @JsonProperty ("*") String asterisk; – extraleon

+0

Неправда. Asterisk - это очень большая проблема при попытке конвертировать звездочку в фактическое имя переменной Java, потому что * - зарезервированное ключевое слово Java. Другими словами, вы не можете иметь String, называемый * в классе Java, поэтому, если вы скопируете ответ JSON как есть и попытаетесь сгенерировать классы POJO на http://www.jsonschema2pojo.org/, вы получите Внутренняя ошибка сервера. –

+1

Согласен, вы не можете иметь переменную с именем * в java. Вот почему я упоминал аннотацию Джексона. Таким образом, вам не нужно указывать переменную «*» в Java POJO, но вы можете дать ей любое имя, которое вам нравится. Jsonschema2pojo.org Генератор POJO, который вы упомянули, является ограниченным инструментом и, по-видимому, не обрабатывает такие случаи. Решение, которое вы предоставили, намного сложнее, чем просто добавление аннотации к полю. – extraleon

2

Вы можете десериализовать JSON в нескольких форматах, используя Jackson. Один из способов, которым вы упоминали, - преобразовать JSON в POJO, что может быть затруднено, когда клавиши являются динамическими. Другой подход заключается в десериализации JSON для модели дерева Джексона, которая называется JsonNode. Ниже показано, как вы можете разобрать предоставленный JSON на JsonNode, а затем получить различные атрибуты.

final ObjectMapper mapper = new ObjectMapper(); 

// Parse the JSON, deserialize to the Tree Model 
final JsonNode jsonNode = mapper.readTree(jsonString); 

// Get hold of the "query -> pages" node. 
final JsonNode pages = jsonNode.path("query").path("pages"); 

// Iterate the pages 
for (final JsonNode page : pages) { 
    // Work with the page object here... 
    System.out.println(page.get("pageid")); // -> 290 
} 

Объект JsonNode является очень гибким и содержит различные удобные функции для доступа к данным. Как показано в приведенном выше примере, методы path() и get() являются двумя способами доступа к данным. Если вы используете get(), свойство ДОЛЖНО существовать, если вы используете path, свойство MAY существует.Кроме того, существует несколько способов итерации подэлементов, и цикл, показанный выше, является одним из способов.

Посмотрите на Jackson docs для получения дополнительной информации.

+0

Да, отличное предложение, и это, безусловно, еще один способ пойти. Он также может комбинировать наши подходы и создавать POJO так, как я описывал, а затем использовать ваше предложение, чтобы просто запросить * контент и установить его в POJO. –

+1

@ TheSaint, звездочка не является проблемой, если вы используете '@JsonProperty (" * ")'. Проблема заключается в анализе динамических данных, где вы фактически не знаете имена свойств («290» в примере). – wassgren

+0

Да, я вижу это сейчас. Хорошая работа и объяснение самостоятельно и @extraleon. –

Смежные вопросы