【问题标题】:How to use Jackson to deserialise an array of objects如何使用 Jackson 反序列化对象数组
【发布时间】:2011-09-15 00:27:35
【问题描述】:

Jackson data binding documentation 表示 Jackson 支持反序列化“所有受支持类型的数组”,但我无法弄清楚具体的语法。

对于单个对象,我会这样做:

//json input
{
    "id" : "junk",
    "stuff" : "things"
}

//Java
MyClass instance = objectMapper.readValue(json, MyClass.class);

现在对于一个数组我想这样做:

//json input
[{
    "id" : "junk",
    "stuff" : "things"
},
{
    "id" : "spam",
    "stuff" : "eggs"
}]

//Java
List<MyClass> entries = ?

有人知道是否有一个神奇的缺失命令吗?如果不是,那么解决办法是什么?

【问题讨论】:

  • 我更喜欢 Google 的 GSON 库来处理 JSON。如果您还没有尝试过,值得一试……让使用它变得非常简单和直观。
  • FWIW Gson 对这个特定问题的可能解决方案与 Jackson 的数据绑定 API 几乎相同。
  • Gweebz -- 也许您想解释一下为什么您认为 GSON 是更好的选择(与 Jackson 相比)?

标签: java json jackson


【解决方案1】:

首先创建一个映射器:

import com.fasterxml.jackson.databind.ObjectMapper;// in play 2.3
ObjectMapper mapper = new ObjectMapper();

作为数组:

MyClass[] myObjects = mapper.readValue(json, MyClass[].class);

作为列表:

List<MyClass> myObjects = mapper.readValue(jsonInput, new TypeReference<List<MyClass>>(){});

另一种指定List类型的方法:

List<MyClass> myObjects = mapper.readValue(jsonInput, mapper.getTypeFactory().constructCollectionType(List.class, MyClass.class));

【讨论】:

  • 额外注意,如果在解析时遇到JsonMappingException: No suitable constructor found for type 之类的错误,则意味着您需要为您的类添加一个默认构造函数,添加一个私有的无参数构造函数为我修复它。
  • @SyntaxRules 如果您有显式构造函数,则必须添加显式构造函数——如果没有,编译器会自动创建公共“空”构造函数。好点子。另一个常见问题是内部类必须是static——否则它们永远不会有零参数构造函数。
  • 顺便说一句,List&lt;MyClass&gt; myObjects = Arrays.asList(mapper.readValue(json, MyClass[].class)) 的运行速度比 TypeRefence 快 10 倍。
  • 我正在寻找一个泛型类型版本。
  • 针对我自己上面的评论,首先将json字符串解析为jsonNode,然后像这样访问数组的属性:JsonNode jsonNode = MAPPER.readTree(json); String arrayString = jsonNode.get("data").toString();然后按照@Programmer Bruce上面的说明进行操作。 List&lt;Source&gt; sources = MAPPER.readValue(arrayString, new TypeReference&lt;List&lt;Source&gt;&gt;() {});
【解决方案2】:

来自Eugene Tskhovrebov

List<MyClass> myObjects = Arrays.asList(mapper.readValue(json, MyClass[].class))

这个解决方案似乎对我来说是最好的。

【讨论】:

  • 对于那些在 Java 中使用代理程序 Lotus Domino 的人来说,这是要走的路。我尝试了其他一些解决方案,但总是得到ResourceNotFoundException
  • 在上述答案的 cmets 中添加 SyntaxRules 可能需要此解决方案,因为我们是为我准备的。我只是想添加它,这样它就不会丢失。
  • Arrays.asList(Json.fromJson(json.get("fieldName"), MyClass[].class))
  • List&lt;MyClass&gt; myObjects = Arrays.asList(mapper.treeToValue(jsonNode.get("fieldName"), MyClass[].class))
  • @CollinKrawll objectmapper.treetovalue 是做什么的?
【解决方案3】:

对于通用实现:

public static <T> List<T> parseJsonArray(String json,
                                         Class<T> classOnWhichArrayIsDefined) 
                                         throws IOException, ClassNotFoundException {
   ObjectMapper mapper = new ObjectMapper();
   Class<T[]> arrayClass = (Class<T[]>) Class.forName("[L" + classOnWhichArrayIsDefined.getName() + ";");
   T[] objects = mapper.readValue(json, arrayClass);
   return Arrays.asList(objects);
}

【讨论】:

  • Class 的构造很好。从来没有见过这个。您从哪里找到有关这方面的信息?
  • 这就是应该用绿旗标记的答案。
【解决方案4】:

首先创建一个线程安全的 ObjectReader 实例。

ObjectMapper objectMapper = new ObjectMapper();
ObjectReader objectReader = objectMapper.reader().forType(new TypeReference<List<MyClass>>(){});

然后使用它:

List<MyClass> result = objectReader.readValue(inputStream);

【讨论】:

  • 我们确实得到了 - com.fasterxml.jackson.databind.JsonMappingException:无法从 [来源:java.io.FileInputStream@33fec21; 的 START_OBJECT 令牌中反序列化 java.util.ArrayList 的实例;行:1,列:1]
  • 这可以通过向我们的 ObjectMapper() 实例添加这个额外的配置层来克服:mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
  • 不工作并出现错误无法从 START_OBJECT 令牌中反序列化 java.util.ArrayList 的实例
【解决方案5】:
try {
    ObjectMapper mapper = new ObjectMapper();
    JsonFactory f = new JsonFactory();
    List<User> lstUser = null;
    JsonParser jp = f.createJsonParser(new File("C:\\maven\\user.json"));
    TypeReference<List<User>> tRef = new TypeReference<List<User>>() {};
    lstUser = mapper.readValue(jp, tRef);
    for (User user : lstUser) {
        System.out.println(user.toString());
    }

} catch (JsonGenerationException e) {
    e.printStackTrace();
} catch (JsonMappingException e) {
    e.printStackTrace();
} catch (IOException e) {
    e.printStackTrace();
}

【讨论】:

    【解决方案6】:

    我无法使用 this answer,因为我的 linter 不允许未经检查的强制转换。

    这是您可以使用的替代方法。我觉得它实际上是一个更清洁的解决方案。

    public <T> List<T> parseJsonArray(String json, Class<T> clazz) throws JsonProcessingException {
      var tree = objectMapper.readTree(json);
      var list = new ArrayList<T>();
      for (JsonNode jsonNode : tree) {
        list.add(objectMapper.treeToValue(jsonNode, clazz));
      }
      return list;
    }
    

    【讨论】:

      【解决方案7】:

      这是一个可以转换 json2object 或 Object2json 的实用程序, 无论你的 pojo(实体 T)

      import java.io.IOException;
      import java.io.StringWriter;
      import java.util.List;
      
      import com.fasterxml.jackson.core.JsonGenerationException;
      import com.fasterxml.jackson.core.JsonParseException;
      import com.fasterxml.jackson.core.type.TypeReference;
      import com.fasterxml.jackson.databind.DeserializationFeature;
      import com.fasterxml.jackson.databind.JsonMappingException;
      import com.fasterxml.jackson.databind.ObjectMapper;
      import com.fasterxml.jackson.databind.SerializationFeature;
      
      /**
       * 
       * @author TIAGO.MEDICI
       * 
       */
      public class JsonUtils {
      
          public static boolean isJSONValid(String jsonInString) {
              try {
                  final ObjectMapper mapper = new ObjectMapper();
                  mapper.readTree(jsonInString);
                  return true;
              } catch (IOException e) {
                  return false;
              }
          }
      
          public static String serializeAsJsonString(Object object) throws JsonGenerationException, JsonMappingException, IOException {
              ObjectMapper objMapper = new ObjectMapper();
              objMapper.enable(SerializationFeature.INDENT_OUTPUT);
              objMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
              StringWriter sw = new StringWriter();
              objMapper.writeValue(sw, object);
              return sw.toString();
          }
      
          public static String serializeAsJsonString(Object object, boolean indent) throws JsonGenerationException, JsonMappingException, IOException {
              ObjectMapper objMapper = new ObjectMapper();
              if (indent == true) {
                  objMapper.enable(SerializationFeature.INDENT_OUTPUT);
                  objMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
              }
      
              StringWriter stringWriter = new StringWriter();
              objMapper.writeValue(stringWriter, object);
              return stringWriter.toString();
          }
      
          public static <T> T jsonStringToObject(String content, Class<T> clazz) throws JsonParseException, JsonMappingException, IOException {
              T obj = null;
              ObjectMapper objMapper = new ObjectMapper();
              obj = objMapper.readValue(content, clazz);
              return obj;
          }
      
          @SuppressWarnings("rawtypes")
          public static <T> T jsonStringToObjectArray(String content) throws JsonParseException, JsonMappingException, IOException {
              T obj = null;
              ObjectMapper mapper = new ObjectMapper();
              obj = mapper.readValue(content, new TypeReference<List>() {
              });
              return obj;
          }
      
          public static <T> T jsonStringToObjectArray(String content, Class<T> clazz) throws JsonParseException, JsonMappingException, IOException {
              T obj = null;
              ObjectMapper mapper = new ObjectMapper();
              mapper = new ObjectMapper().configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
              obj = mapper.readValue(content, mapper.getTypeFactory().constructCollectionType(List.class, clazz));
              return obj;
          }
      

      【讨论】:

        【解决方案8】:

        试试这个

        List<MyClass> list = mapper.readerForListOf(MyClass.class).readValue(json)
        

        【讨论】:

          【解决方案9】:

          你也可以创建一个扩展ArrayList的类:

          public static class MyList extends ArrayList&lt;Myclass&gt; {}

          然后像这样使用它:

          List<MyClass> list = objectMapper.readValue(json, MyList.class);
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-02-07
            • 2020-08-07
            • 1970-01-01
            • 2019-10-25
            • 2014-02-12
            相关资源
            最近更新 更多