【问题标题】:Parsing a JSONArray object, containing JSON arrays, to a list of JSON arrays将包含 JSON 数组的 JSONArray 对象解析为 JSON 数组列表
【发布时间】:2019-09-09 11:36:13
【问题描述】:

我正在使用包含 JSON 数组的 PrimeFaces JSONArray 对象,例如(简化)

[['james', 12, 2019], ['sarah', 29, 2015], ['robert', 15, 2011]]

作为静态构建方法的输入,该方法在嵌套数组的字段上运行以构造表示其数据的 POJO。我使用实体和实体容器类中的静态构建方法来实现这一点(后者只是解析 JSON 并调用前一个构建方法来构造每个实体)。这适用于粗略的 for 循环:

public static MyContainer buildContainer(JSONArray json) {
    MyContainer list = new MyContainer ();
    for (int i = 0; i < json.length(); i++) {
        MyEntity ent = MyEntity.buildEntity(json, i);
        list.add(ent);
    }
    return list;
}

但我想要一个更优雅的解决方案,尤其是使用函数式方法的解决方案(如果没有更好的理由,可以提高我对函数式 Java 的了解)。我使用 Jackson 将代表我的完整数据集的 JSONArray 解析为 JSONArrays 数组( JSONArray[])。然后可以将此数组转换为列表,从而更轻松地进行功能操作。这是我最初尝试写下我认为的样子,这可能表明了对 Jackson 和函数式 Java 的一些基本误解:

public static MyContainer buildContainer(JSONArray json) {
    ObjectMapper mapper = new ObjectMapper();
    try {
        JSONArray[] jaArr = mapper.readValue(json.toString(), JSONArray[].class);
        List<JSONArray> jaList = Arrays.asList(jaArr);
        MyContainer list = (MyContainer) (List<MyEntity>) Arrays.asList(json)
                .stream()
                .map(MyEntity::buildEntity)
                .collect(Collectors.toList());
        return list;
    } catch (JsonProcessingException ex) {
        return null;
    }
}

Netbeans 不建议这样做有什么问题,并且不存在编译时问题。然而,在运行时,我得到了异常

Severe: com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of org.primefaces.json.JSONArray out of START_ARRAY token.

所以,我的问题是为什么会出现这个异常,当输入是我上面显示的格式时,是否有比将 JSONArray 序列化为字符串然后将其作为 JSONArray[] 读回更优雅的解决方案 - 我可以更直接地将我的初始 JSONArray 转换为允许 .stream().forEach() 的类型吗?

【问题讨论】:

  • MyEntityPOJO,数组中的每个元素都有 3 个属性:['james', 12, 2019]?看起来MyContainer 实现了List 接口。为什么需要自己的实现?
  • 这是一个简化的例子;真实案例中的字段更多,数据类型多样。我的容器类确实实现了 List;它是一个带有附加字段的自定义列表,因为它还需要包含有关其中对象的统计信息。这在应用程序的其他地方使用,但与此处的问题无关。
  • JSONArray 类来自哪个包?
  • 它是 org.primefaces.json.JSONArray 的一个实例,正如您在我发布的异常中看到的那样

标签: java json parsing functional-programming jackson


【解决方案1】:

JSONArray 在版本7.0 中实现Iterable,所以你可以这样做:

StreamSupport
  .stream(iterable.spliterator(), false)
  .map(MyEntity::buildEntity)
  .collect(Collectors.toList());

另见:

【讨论】:

  • 谢谢,这正是我所需要的。我唯一需要做的就是在调用构建方法{java} public static MyContainer build(JSONArray json) { return fromList( StreamSupport .stream(json.spliterator(), false) .map(array -&gt; (JSONArray) array) .map(MyEntity::buildEntity) .collect(Collectors.toList()) ); } 之前进行逐个元素的类型转换
猜你喜欢
  • 1970-01-01
  • 2021-03-19
  • 2023-03-22
  • 2020-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-02
相关资源
最近更新 更多