Java - Как десериализовать массив JSON с вложенными объектами и списками?

Как десериализовать строку JSON, содержащую списки объектов внутри других объектов? Я нашел объяснения простой десериализации, но не могу многого из них экстраполировать, так как все они немного ошибочны. Например (POJO опущены), для

String json = "[ {
  "id" : 33147,
  "name" : "Refinancing",
  "photos" : [ {
    "name" : "347.png",
    "url" : "/loans/568/photos/092"
  } ],
  "username" : "zach1985"
} , {
  "id" : 7693,
  "name" : "Stuff",
  "photos" : [ {
    "name" : "newpic1.png",
    "url" : "/loans/123446/photos/890"
  } ],
  "username" : "sengaia"
} ]";

ArrayList<Ad> ads = new ArrayList<>;

deserialize(json, ads);

System.out.println(ads.get(1).getName());
System.out.println(ads.get(0).getPhotos().get(0).getName());

Выходные данные будут «Stuff» и «347». Как тогда должен быть реализован метод deserialize()?


person Sargon1    schedule 02.06.2016    source источник
comment
Вы не можете десериализовать это в массив. Аралист содержит только 1 ключ без значения. Я предлагаю вам использовать HashMap. РЕДАКТИРОВАТЬ: К сожалению, я не видел, что это массив JSON.   -  person Martacus    schedule 02.06.2016
comment
@Martacus Это массив JSON.   -  person Sotirios Delimanolis    schedule 02.06.2016
comment
new ObjectMapper().readValue(data, FullyTypedThing.class) выполнит свою работу, если FullyTypedThing будет именно тем, что написано на банке: состоит из других полностью типизированных классов или коллекций полностью типизированных классов. Вы даже можете назвать их все Embedded и определить как public static вложенных классов в тех местах, где они будут использоваться. Вам действительно нужен пример или вам удастся определить класс самостоятельно?   -  person Oleg Sklyar    schedule 02.06.2016
comment
Вопрос. Как десериализовать строку JSON, содержащую списки объектов внутри других объектов? О: Есть много разных способов. Если вы планируете более активно работать с JSON в Java, я рекомендую ознакомиться с Джексоном: mkyong.com/java/how-to-convert-java-object-to-from-json-jackson   -  person paulsm4    schedule 02.06.2016
comment
Как указывали другие, изучите структуру JSON, такую ​​​​как Джексон. Затем используйте ObjectMapper для преобразования вашего JSON в объекты. @Oleg указал, что вы можете использовать: new ObjectMapper().readValue(data, FullyTypedThing.class) - если вы хотите прочитать массив, просто передайте массив этого класса тому же методу, что и в: new ObjectMapper().readValue(data, FullyTypedThing[].class   -  person CloudNinja    schedule 02.06.2016
comment
Вам также может понадобиться настроить ObjectMapper в зависимости от ваших требований (у Джексона есть несколько вариантов). Но я думаю, что просто начните, а затем попробуйте настроить ObjectMapper, если потребуется, вызвав его методы #configure(..) и #setVisibility(..).   -  person CloudNinja    schedule 02.06.2016
comment
@Oleg Я попробую сначала привязать примеры, предоставленные мной, к моему делу, спасибо.   -  person Sargon1    schedule 02.06.2016
comment
Я просто поместил исполняемый пример в ответ. Я утверждаю, что это дубликат, поскольку исходный ответ довольно хромой (я имею в виду дублирующий вопрос и ответ на исходный вопрос)...   -  person Oleg Sklyar    schedule 02.06.2016


Ответы (1)


Как я указал в комментарии к вопросу, вот тест, который показывает, как это сделать:

public class JSONTest {

  public static class FullyTypedThing {
    public int id;
    public String name;
    public List<Photos> photos = Lists.newArrayList();
    public String username;

    public static class Photos {
      public String name;
      public String url;
    }
  }

  private static final String json = "[ { \"id\" : 33147,    \"name\" : \"Refinancing\", \"photos\" : [ {"
    + "\"name\" : \"347.png\", \"url\" : \"/loans/568/photos/092\"  } ],"
    + "\"username\" : \"zach1985\"} , {  \"id\" : 7693,  \"name\" : \"Stuff\","
    + "\"photos\" : [ {  \"name\" : \"newpic1.png\",  \"url\" : \"/loans/123446/photos/890\"  } ],"
    + "\"username\" : \"sengaia\"  } ]";

  @Test
  public void roundtrip() throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    List<FullyTypedThing> res = Lists.newArrayList(
      mapper.readValue(json, FullyTypedThing[].class));
    assertEquals(2, res.size());
    assertEquals(33147, res.get(0).id);
    assertEquals("Refinancing", res.get(0).name);
    assertEquals("347.png", res.get(0).photos.get(0).name);
    assertEquals("/loans/568/photos/092", res.get(0).photos.get(0).url);
    assertEquals(7693, res.get(1).id);
    assertEquals("Stuff", res.get(1).name);
    assertEquals("newpic1.png", res.get(1).photos.get(0).name);
    assertEquals("/loans/123446/photos/890", res.get(1).photos.get(0).url);

    assertEquals("[{\"id\":33147,\"name\":\"Refinancing\",\"photos\":"
      + "[{\"name\":\"347.png\",\"url\":\"/loans/568/photos/092\"}],"
      + "\"username\":\"zach1985\"},{\"id\":7693,\"name\":\"Stuff\","
      + "\"photos\":[{\"name\":\"newpic1.png\",\"url\":\"/loans/123446/photos/890\"}],"
      + "\"username\":\"sengaia\"}]", mapper.writeValueAsString(res));

  }
}
person Oleg Sklyar    schedule 02.06.2016
comment
Несколько уточнений: 1) под ObjectMapper вы подразумеваете библиотеку Джексона: github.com/FasterXML/jackson , 2) в вашем примере вы используете mapper.readValue(..., FullyTypedThing.class). Хорошо. Но Джексон ТАКЖЕ позволяет вам получать доступ к объектам JSON БЕЗ обязательного определения соответствующего класса Java, если это необходимо. - person paulsm4; 02.06.2016
comment
Да, я использую Jackson, который де-факто является стандартом. Что касается вашего второго пункта, я не вижу смысла. Я знаю, что могу это сделать, и что? Зачем мне нетипизированные данные и много кода для синтаксического анализа, если я могу правильно напечатать их и сделать в одну строку, прозрачно, ясно и безопасно? Определение класса-держателя, подобного тому, что используется в этом тесте, занимает 5 минут даже для более сложных структур данных. Да, при работе с разнородными коллекциями можно прибегнуть к необработанному доступу, но тогда я бы поставил под сомнение причины разнородности этих данных. Чаще всего это плохой дизайн. - person Oleg Sklyar; 03.06.2016