Java - 如何反序列化带有嵌套对象和列表的 JSON 数组? [复制]

Posted

技术标签:

【中文标题】Java - 如何反序列化带有嵌套对象和列表的 JSON 数组? [复制]【英文标题】:Java - How to deserialize a JSON array with nested objects and lists? [duplicate] 【发布时间】:2016-10-02 16:51:10 【问题描述】:

如何反序列化包含其他对象中的对象列表的 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()方法需要如何实现呢?

【问题讨论】:

您不能将其反序列化为数组列表。一个数组列表只包含 1 个没有值的键。我建议你使用 HashMap。编辑:糟糕,我没有看到它是一个 JSON 数组。 @Martacus 这是一个 JSON 数组。 问:如何反序列化包含其他对象中的对象列表的 JSON 字符串? A:有很多不同的方法。如果您计划在 Java 中更广泛地使用 JSON,我建议您熟悉 Jackson:mkyong.com/java/how-to-convert-java-object-to-from-json-jackson 正如其他人所指出的 - 学习像杰克逊这样的 JSON 框架。然后使用ObjectMapper 将您的 JSON 转换为对象。 @Oleg 表示您可以使用:new ObjectMapper().readValue(data, FullyTypedThing.class) - 如果您想读取数组,只需将该类的数组传递给相同的方法,如:new ObjectMapper().readValue(data, FullyTypedThing[].class 您可能还需要根据您的要求配置ObjectMapper(Jackson 有几个选项)。但我认为刚刚开始 - 然后尝试通过调用 #configure(..)#setVisibility(..) 方法来调整 ObjectMapper 【参考方案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));

  

【讨论】:

一些澄清:1)通过“ObjectMapper”,你的意思是“杰克逊图书馆”:github.com/FasterXML/jackson,2)在你的例子中,你使用mapper.readValue(..., FullyTypedThing.class)。还行吧。但是 Jackson ALSO 允许您访问 JSON 实体 WITHOUT 必须定义相应的 Java 类(如果需要)。 是的,我使用 Jackson,这是事实上的标准。关于你的第二点,我没有看到这一点。我知道我能做到,那又如何?如果我可以在一行中正确地键入和完成,透明、清晰和类型安全,我为什么需要无类型的数据和大量的解析代码?定义一个持有者类,就像这个测试中的一样,是一个 5 分钟的工作,即使对于更复杂的数据结构也是如此。是的,当使用异构集合时,可能会求助于原始访问,但我会质疑数据异构背后的原因。往往是糟糕的设计。

以上是关于Java - 如何反序列化带有嵌套对象和列表的 JSON 数组? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何正确地将 JSON 字符串反序列化为包含另一个类的嵌套列表的类

如何反序列化包含同一类嵌套的json类(Unity C#)?

Spring RestTemplate在尝试反序列化嵌套的对象列表时返回null对象

在 Android Studio 中将嵌套的 JSON 反序列化为 Java

使用嵌套映射的 JSON 对象反序列化,Java Spring

将嵌套的 JSON 字符串反序列化为 Java 对象