【问题标题】:How to parse nested arrays with Jackson?如何用杰克逊解析嵌套数组?
【发布时间】:2014-08-08 01:22:46
【问题描述】:

我曾经成功解析过以下.json文件:

[
    {
        "latitude": 49.419459253939316,
        "longitude": 8.676411621072491
    },
    {
        "latitude": 49.41946061080915,
        "longitude": 8.676411644939083
    },
    {
        "latitude": 49.420365910782735,
        "longitude": 8.676438042403413
    }
]

以下Jackson script 输出List 个点。

private static <T> List<T> parseFile(final String fileName, 
                                     Class<T> contentType) {
    // ...
    InputStream inputStream = // Open file
    ObjectMapper objectMapper = new ObjectMapper();
    try {
        TypeFactory typeFactory = objectMapper.getTypeFactory();
        CollectionType collectionType = typeFactory
            .constructCollectionType(List.class, contentType);
        return objectMapper.readValue(inputStream, collectionType);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

现在数据集变得更加复杂。点的List 变为点的ListList。 我是这样组织的 - 如果这不正确,请纠正我。

[
    [
        {
            "latitude": 49.419459253939316,
            "longitude": 8.676411621072491
        },
        {
            "latitude": 49.41946061080915,
            "longitude": 8.676411644939083
        },
        {
            "latitude": 49.420365910782735,
            "longitude": 8.676438042403413
        }
    ],
    [
        {
            "latitude": 49.40460334213399,
            "longitude": 8.670034018853409
        },
        {
            "latitude": 49.404608057285145,
            "longitude": 8.670028775634165
        },
        {
            "latitude": 49.40506145685422,
            "longitude": 8.66955817506422
        }
    ]
]

我准备了以下 POJO 来将数据存储到:

public class GeoPoint {
    public double latitude;
    public double longitude;
}

...

public class ThreePoints {
    public List<GeoPoint> points;  
}

如何更改上面的 Jackson 解析器以便它可以处理嵌套数组? Jackson 能否将数据解析成ThreePoints.class 之类的嵌套类结构?

【问题讨论】:

    标签: java json generics jackson multidimensional-array


    【解决方案1】:

    您可以简单地创建其他集合类型。见以下代码:

    TypeFactory typeFactory = mapper.getTypeFactory();
    CollectionType listType = typeFactory.constructCollectionType(List.class, contentType);
    CollectionType listListType = typeFactory.constructCollectionType(List.class, listType);
    List<List<GeoPoint>> readValue = mapper.readValue(json, rootCollectionType);
    // convert to ThreePoints
    

    编辑
    不幸的是,您无法告诉 Jackson 将您的 JSON 转换为您的 POJO 课程,因为它们彼此不适合。 Jackson 也不包含可用于将 JSON 映射到 POJO 类的注释。您必须手动完成。使用我的代码,您可以为 ThreePoints 类编写自定义反序列化器,您可以在其中使用内部 ObjectMapper 和我上面的代码。我认为,您将能够轻松地将 List&lt;List&lt;GeoPoint&gt;&gt; readValue 转换为 ThreePoints 类。另一种选择 - 您可以在 JsonUtil 类中编写一个简单的函数。如果您真的无法更改此JSON,则必须手动进行。

    【讨论】:

    • 您能否更新您的解决方案以展示我如何生成List&lt;ThreePoints&gt;
    【解决方案2】:

    你可以编写一个简单的自定义反序列化器

    要将其反序列化到您的类:

    public class GeoPoint {
        public double latitude;
        public double longitude;
    }
    
    public class ThreePoints {
        public List<GeoPoint> points;
    }
    

    编写自定义反序列化器:

    class ThreePointsDeserializer extends StdDeserializer<ThreePoints> {
    
        protected ThreePointsDeserializer() {
            super(ThreePoints.class);
        }
    
    
        @Override
        public ThreePoints deserialize(JsonParser parser, DeserializationContext ctx)
                throws IOException, JsonProcessingException {
            ThreePoints result = new ThreePoints();
            GeoPoint[] points = parser.getCodec().readValue(parser, GeoPoint[].class);
            result.points = Arrays.asList(points);
            return result;
        }
    }
    

    使用该反序列化器:

    SimpleModule module = new SimpleModule();
    module.addDeserializer(ThreePoints.class, new ThreePointsDeserializer());
    
    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(module);
    
    TypeFactory tf = mapper.getTypeFactory();
    CollectionType collectionType = tf.constructCollectionType(List.class, ThreePoints.class);
    
    List<ThreePoints> result = mapper.readValue(YOUR_DATA, collectionType);
    

    【讨论】:

      【解决方案3】:

      在我看来,最优雅的解决方案是使用 TypeReference

      ObjectMapper mapper = new ObjectMapper();
      TypeReference<List<List<GeoPoint>>> typeRef = new TypeReference<List<List<GeoPoint>>>() {};
      List<List<GeoPoint>> locations = mapper.readValue(jsonAsString, typeRef);
      

      【讨论】:

        【解决方案4】:

        您需要将值读取为矩阵, 首先,您需要使用名为 Place 的 Pojo 映射值。

        public class Place {
        
            double latitude;
            double longitude;
        
            public double getLatitude() {
                return latitude;
            }
        
            public void setLatitude(double latitude) {
                this.latitude = latitude;
            }
        
            public double getLongitude() {
                return longitude;
            }
        
            public void setLongitude(double longitude) {
                this.longitude = longitude;
            }
        }       
        

        第二步,需要将JsonNode映射成一个Matrix。

        import java.io.IOException;
        import java.util.List;
        import org.codehaus.jackson.JsonNode;
        import org.codehaus.jackson.map.ObjectMapper;
        import org.codehaus.jackson.map.type.CollectionType;
        import org.codehaus.jackson.map.type.TypeFactory;
        
        
        public class Main {
           static String jsonString =  "[" +
        "    [" +
        "        {" +
        "            \"latitude\": 49.419459253939316," +
        "            \"longitude\": 8.676411621072491" +
        "        }," +
        "        {" +
        "            \"latitude\": 49.41946061080915," +
        "            \"longitude\": 8.676411644939083" +
        "        }," +
        "        {" +
        "            \"latitude\": 49.420365910782735," +
        "            \"longitude\": 8.676438042403413" +
        "        }" +
        "    ]," +
        "    [" +
        "        {" +
        "            \"latitude\": 49.40460334213399," +
        "            \"longitude\": 8.670034018853409" +
        "        }," +
        "        {" +
        "            \"latitude\": 49.404608057285145," +
        "            \"longitude\": 8.670028775634165" +
        "        }," +
        "        {" +
        "            \"latitude\": 49.40506145685422," +
        "            \"longitude\": 8.66955817506422" +
        "        }" +
        "    ]" +
        "]";
        
            public static void main(String...args) {
                final ObjectMapper om = new ObjectMapper();
                try {
                   final Place[][] dtos = om.readValue(new ObjectMapper()
                       .readValue(jsonString, JsonNode.class), Place[][].class);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        

        干杯。

        【讨论】:

        • 我想让它解析成List
        猜你喜欢
        • 2015-02-04
        • 1970-01-01
        • 2014-08-22
        • 2019-11-25
        • 2014-06-17
        • 1970-01-01
        • 1970-01-01
        • 2012-09-11
        • 1970-01-01
        相关资源
        最近更新 更多