Как использовать Google Gson API для правильной десериализации JSON? - PullRequest
22 голосов
/ 19 мая 2010

Вкратце, это эскиз объекта JSON, который я хочу проанализировать в JAVA:

{
    object1: {
            item1: //[String | Array | Object] ,
            item2: // ...
            //<> more items
    object2: { /* .. */ }
    //<> more objects
}

Это POJO s, которые я создал для анализа (для краткости опущу import утверждения):

(1) Представление полного объекта JSON

public class JObjectContainer {

    private List<JObject> jObjects ;

    public JObjectContainer() { }

    //get & set methods

}

(2) Представление вложенных объектов:

 public class JObject {

    private String id ;
    private List<JNode> jObjects ;

    public JObject() { } 

    //get & set methods

}

(3) Представление предметов:

 public class JNode {

    private JsonElement item1 ;
    private JsonElement item2 ;
    //<> more item fields

    public JNode() { }

    //get & set methods

}

Теперь создаем экземпляр Gson (FileReader для импорта jsonFile),

 Gson gson = new Gson() ;
 JObjectContainer joc = gson.fromJson(jsonFile,JObjectContainer.class) ;

Я получаю NullPointerException всякий раз, когда пытаюсь получить доступ к анализируемому объекту (например, через ListIterator). Gson делает , однако создает объект указанного класса, а не генерирует никаких последующих ошибок.

Я знаю, что это было сделано раньше. Итак, что мне не хватает?

ТИА

Ответы [ 2 ]

37 голосов
/ 19 мая 2010

Это невозможно. Вам необходимо изменить структуру JSON, чтобы она представляла object1, object2 и т. Д. Как элементы массива . Прямо сейчас это свойства объекта, число которых, очевидно, неизвестно (иначе вы не пытались отобразить его как List). Gson умный, но не тот умный :)

Итак, в качестве базового примера, эта структура JSON с массивом:

{ nodes:
  [
    { item1: 'value1a', item2: 'value2a' },
    { item1: 'value1b', item2: 'value2b' },
    { item1: 'value1c', item2: 'value2c' }
  ]
}

в сочетании с представлением Java (которое не обязательно должно называться POJO, а просто объектом javabean или модели или объектом значения).

public class Container {
    private List<Node> nodes;
    // +getter.
}

public class Node {
    private String item1;
    private String item2;
    // +getters.
}

и этот звонок Gson

Container container = new Gson().fromJson(json, Container.class);

должно работать.

Обновление : для ясности, проблема в структуре JSON, а не в структуре объектов Java. Предполагая, что ваша структура Java-объекта именно то, что вы хотели бы получить, ваша структура JSON должна выглядеть следующим образом, чтобы заставить Gson выполнить свою работу:

{ jObjects:
  [
    { id: 123, jObjects: 
      [
        { item1: 'value1a', item2: 'value2a' },
        { item1: 'value1b', item2: 'value2b' },
        { item1: 'value1c', item2: 'value2c' }
        /* etc... commaseparated */
      ]
    },
    { id: 456, jObjects: 
      [
        { item1: 'value1d', item2: 'value2d' },
        { item1: 'value1e', item2: 'value2e' },
        { item1: 'value1f', item2: 'value2f' }
        /* etc... commaseparated */
      ]
    }
    /* etc... commaseparated */
  ]
}

Только свойство JsonElement должно быть заменено на String, так как оно недействительно.

0 голосов
/ 21 августа 2010

Я думаю, что BalusC дал хорошие указатели для конкретного вопроса относительно GSon (и вообще, привязка данных один к одному); но на тот случай, если вы считаете, что должна быть более динамичная обработка, вы можете также рассмотреть другие пакеты обработки JSON. Многие пакеты имеют дополнительные или альтернативные способы сопоставления вещей: Json-lib, flexjson и Jackson имеют, по крайней мере, дополнения по сравнению с Gson. Некоторые предлагают более слабое отображение (вы определяете имена вещей для типов), другие - фактическую поддержку для полиморфных типов (объявление объекта, но на самом деле он может отображаться на подтип, который был сериализован).

...