[英]How to parse nested arrays with Jackson?
I used to successfully parse the following .json file:我曾经成功解析过以下 .json 文件:
[
{
"latitude": 49.419459253939316,
"longitude": 8.676411621072491
},
{
"latitude": 49.41946061080915,
"longitude": 8.676411644939083
},
{
"latitude": 49.420365910782735,
"longitude": 8.676438042403413
}
]
The following Jackson script outputs a List
of points.以下Jackson 脚本输出一个点
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;
}
Now the dataset gets more complicated.现在数据集变得更加复杂。 The
List
of points becomes a List
of List
of points.点
List
变成点List
List
。 I structured it this way - please correct me if this is not correct.我是这样构建的 - 如果这不正确,请纠正我。
[
[
{
"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
}
]
]
I prepared the following POJOs to store the data into:我准备了以下 POJO 来存储数据:
public class GeoPoint {
public double latitude;
public double longitude;
}
... ...
public class ThreePoints {
public List<GeoPoint> points;
}
How do I have to change the above Jackson parser so it can handle the nested arrays?我必须如何更改上面的 Jackson 解析器才能处理嵌套数组? Can Jackson parse the data into a nested class structure such as the
ThreePoints.class
? Jackson 能否将数据解析为嵌套的类结构,例如
ThreePoints.class
?
You can simply create additional collection type.您可以简单地创建其他集合类型。 See below code:
见下面的代码:
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
EDIT编辑
Unfortunately you are not able to tell Jackson
to convert your JSON
to your POJO
classes because they do not fit to each other.不幸的是,您无法告诉
Jackson
将您的JSON
转换为您的POJO
类,因为它们不适合彼此。 Jackson
also does not contain annotations which you can use to map your JSON
to your POJO
classes. Jackson
也不包含可用于将JSON
映射到POJO
类的注释。 You have to do it manually.你必须手动完成。 Using my code you can write custom deserializer for
ThreePoints
class in which you can use inner ObjectMapper
and my above code.使用我的代码,您可以为
ThreePoints
类编写自定义反序列化器,您可以在其中使用内部ObjectMapper
和我上面的代码。 I think, that you will be able easily convert List<List<GeoPoint>> readValue
to ThreePoints
class.我认为,您可以轻松地将
List<List<GeoPoint>> readValue
转换为ThreePoints
类。 Another option - you can write just a simple function in you JsonUtil
class.另一种选择 - 您可以在
JsonUtil
类中编写一个简单的函数。 If you really can not change this JSON
you have to do it manually.如果您真的无法更改此
JSON
,则必须手动进行。
You can write a simple custom deserializer您可以编写一个简单的自定义反序列化器
To deserialize it to your class:要将其反序列化到您的班级:
public class GeoPoint {
public double latitude;
public double longitude;
}
public class ThreePoints {
public List<GeoPoint> points;
}
Write a custom deserializer:编写自定义解串器:
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;
}
}
to use that deserializer:使用该解串器:
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);
you need to read the values as Matrix, first you need to map the values using a Pojo called Place.您需要将值读取为矩阵,首先您需要使用名为 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;
}
}
Second step, you need to map the JsonNode into a Matrix.第二步,你需要将 JsonNode 映射成一个矩阵。
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();
}
}
}
Cheers.干杯。
In my opinion the most elegant solution would be to use TypeReference在我看来,最优雅的解决方案是使用 TypeReference
ObjectMapper mapper = new ObjectMapper();
TypeReference<List<List<GeoPoint>>> typeRef = new TypeReference<List<List<GeoPoint>>>() {};
List<List<GeoPoint>> locations = mapper.readValue(jsonAsString, typeRef);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.