Reputation: 51824
I used to successfully parse the following .json file:
[
{
"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.
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.
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:
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? Can Jackson parse the data into a nested class structure such as the ThreePoints.class
?
Upvotes: 1
Views: 5534
Reputation: 1825
In my opinion the most elegant solution would be to use TypeReference
ObjectMapper mapper = new ObjectMapper();
TypeReference<List<List<GeoPoint>>> typeRef = new TypeReference<List<List<GeoPoint>>>() {};
List<List<GeoPoint>> locations = mapper.readValue(jsonAsString, typeRef);
Upvotes: 1
Reputation: 358
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);
Upvotes: 1
Reputation: 38655
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
also does not contain annotations which you can use to map your JSON
to your POJO
classes. 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. I think, that you will be able easily convert List<List<GeoPoint>> readValue
to ThreePoints
class. Another option - you can write just a simple function in you JsonUtil
class. If you really can not change this JSON
you have to do it manually.
Upvotes: 3
Reputation: 2603
you need to read the values as Matrix, first you need to map the values using a Pojo called Place.
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.
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.
Upvotes: 0