【问题标题】:Jackson read json in generic List杰克逊在通用列表中读取 json
【发布时间】:2013-08-01 12:11:12
【问题描述】:

我正在使用 Jackson 来读取 json 消息。我试图解析的值之一是 List,另一个值包含列表中数据的类型。这是我在 java 中创建的结构。

public class Message<T> {
   private Timestamp time;
   private RestAction action;
   private String type;
   private List<T> data;
}

通过Class.forName(); 我可以得到代表列表中数据的类。问题是我如何阅读列表。

【问题讨论】:

  • 您能向我们展示您已经编写的示例 JSON 字符串和源代码吗?我想你也可以看到这个问题:stackoverflow.com/questions/17605524/…
  • 如果您不介意,请将我的答案标记为有效答案,该答案获得了大部分分数。它结构紧凑,完全满足您的需求。

标签: java json list jackson


【解决方案1】:

更短的东西:

mapper.readValue(jsonString, new TypeReference<List<EntryType>>() {});

EntryType 是对您希望在集合中保存的类型的引用。它可能是任何 Java 类。 例如,要读取 JSON 表示,例如 ["a", "b", "c"],mapper 的第二个参数应该是 new TypeReference&lt;List&lt;String&gt;&gt;() {}

【讨论】:

  • 它有效。也试试这个:Iterator it = mapper.reader(Objects.class).readValues(in);
  • Objects.class 来自哪里?
  • 它属于列表中的类型(您的示例中的EntryType)
  • 这个答案没有说明EntryType来自哪里!
  • 这没有回答这个问题,它专门说“在通用列表中读取json”。如果你要使用这段代码,通过将EntryType替换为泛型T,你会得到错误:java.util.LinkedHashMap cannot be cast to ...(更多信息请参考这篇文章:baeldung.com/jackson-linkedhashmap-cannot-be-cast)正确的解决方案是the accepted answer by alex ,它的赞成票比这个答案少。
【解决方案2】:

自 2.11 版(2020 年 4 月)以来,Jackson 拥有 readerForListOf 方法 (documentation):

ObjectMapper mapper = ObjectMapper().configure(...);
ObjectReader reader = mapper.readerForListOf(MyClass.class);
List<MyClass> list = reader.readValue(...);

【讨论】:

    【解决方案3】:

    如果需要读取泛型List中的json, 做类似的事情

    {
        Employee:
        [
            {
                "key": "value",
                "key": "value"
            },
            {
                "key": "value",
                "key": "value"
            }
        ]
    } 
    

    你的 json 列表对象 和 你的 bean 类是

    class person {
    private String key;
    private String value;
    }
    

    现在您可以使用 HashMap 读取此 json

    类似

    TypeReference<HashMap<String,List<Person>>> personList =  new   TypeReference<HashMap<String, List<Person>>>() {};
    
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    
    HashMap<String, List<Person>> employees = objectMapper.readValue(request.getInputStream(), personList);
    

    【讨论】:

      【解决方案4】:

      如果您需要将传入的 json 映射到您的列表,您可以这样做

      String jsonString = ...; //Your incoming json string
      ObjectMapper mapper = new ObjectMapper();
      Class<?> clz = Class.forName(yourTypeString);
      JavaType type = mapper.getTypeFactory().constructCollectionType(List.class, clz);
      List <T> result = mapper.readValue(jsonString, type);
      

      编辑

      类似的东西,完全未经测试,从未做过

      public Message<T> deserialize(JsonParser jsonParser, DeserializationContext arg1)
          throws IOException, JsonProcessingException {
          ObjectMapper mapper = new ObjectMapper();
          ObjectCodec oc = jsonParser.getCodec();
          JsonNode node = oc.readTree(jsonParser);
      
          JsonNode timeStamp = node.get("time");
          Timestamp time = mapper.readValue(timeStamp, Timestamp.class);
          JsonNode restAction = node.get("action");
          RestAction action = mapper.readValue(restAction, RestAction.class);
          String type = node.get("type").getTextValue();
          Class<?> clz = Class.forName(type);
          JsonNode list = node.get("data");
          JavaType listType = mapper.getTypeFactory().constructCollectionType(List.class,   clz);
          List <T> data = mapper.readValue(list, listType);
      
          Message<T> message = new Message<T>;
          message.setTime(time);
          message.setAction(action);
          message.setType(type);
          message.setData(data);
      
          return message;
      }
      

      【讨论】:

      • 好的...我已经尝试过这样解决,但问题是 json 消息除了列表之外还有其他字段。
      • 糟糕,我不明白你的问题。然后你需要创建一个像 seralex.vi 说的反序列化器。您可以在其中使用类似的东西来反序列化列表
      • 编辑了我的答案,让我知道它是否有效,我可能很快就会做类似的事情
      • thnx 的答案......实际上结合你的答案和 seralex 的答案帮助我解决了它(写一些类似于你编辑的答案的东西)。由于其他问题没有机会尝试它,但我认为这部分已经完成。再次感谢!
      【解决方案5】:

      您需要使用 @JsonDeserialize(using = MessageDeserializer.class) 注释您的类并实现自定义反序列化器:

      public class MessageDeserializer extends JsonDeserializer<Message> {
        @Override
        public Message deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
          throws IOException, JsonProcessingException {
          // YOU DESERIALIZER CODE HERE
        }
      }
      

      @在此处查看示例:How Do I Write a Jackson JSON Serializer & Deserializer?

      【讨论】:

        猜你喜欢
        • 2012-01-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-07
        • 1970-01-01
        • 2015-07-28
        • 2019-11-25
        • 1970-01-01
        相关资源
        最近更新 更多