Jackson JsonNode to typed Collection
Asked Answered
T

3

40

What is the proper way to convert a Jackson JsonNode to a java collection?

If it were a json string I could use ObjectMapper.readValue(String, TypeReference) but for a JsonNode the only options are ObjectMapper.treeToValue(TreeNode, Class) which wouldn't give a typed collection, or ObjectMapper.convertValue(Object, JavaType) which feels wrong on account of its accepting any POJO for conversion.

Is there another "correct" way or is it one of these?

Toneless answered 30/8, 2016 at 22:8 Comment(0)
C
87

Acquire an ObjectReader with ObjectMapper#readerFor(TypeReference) using a TypeReference describing the typed collection you want. Then use ObjectReader#readValue(JsonNode) to parse the JsonNode (presumably an ArrayNode).

For example, to get a List<String> out of a JSON array containing only JSON strings

ObjectMapper mapper = new ObjectMapper();
// example JsonNode
JsonNode arrayNode = mapper.createArrayNode().add("one").add("two");
// acquire reader for the right type
ObjectReader reader = mapper.readerFor(new TypeReference<List<String>>() {
});
// use it
List<String> list = reader.readValue(arrayNode);
Childbed answered 30/8, 2016 at 22:19 Comment(1)
In older Jackson versions (2.5 and before), there is no readerFor() method. Use the reader() method instead.Hanukkah
C
13

If an Iterator is more useful...

...you can also use the elements() method of ArrayNode. Example see below.

sample.json

{
    "first": [
        "Some string ...",
        "Some string ..."
    ],
    "second": [
        "Some string ..."
    ]
}

So, the List<String> is inside one of the JsonNodes.

Java

When you convert that inner node to an ArrayNode you can use the elements() method, which returns an Iterator of JsonNodes.

File file = new File("src/test/resources/sample.json");
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode = mapper.readTree(file);
ArrayNode arrayNode = (ArrayNode) jsonNode.get("first");
Iterator<JsonNode> itr = arrayNode.elements();
// and to get the string from one of the elements, use for example...
itr.next().asText();

New to Jackson Object Mapper?

I like this tutorial: https://www.baeldung.com/jackson-object-mapper-tutorial

Update:

You can also use .iterator() method of ArrayNode. It is the same:

Same as calling .elements(); implemented so that convenience "for-each" loop can be used for looping over elements of JSON Array constructs.

from the javadocs of com.fasterxml.jackson.core:jackson-databind:2.11.0

Crescent answered 9/7, 2020 at 19:48 Comment(2)
is there any way to one-line the iteration of the array into a List<>? I m using a for loop to iterate over the JsonNode/ArrayNode and adding it to a list, but I was hoping for something that I could just ArrayNode.asList() or somethingPsychognosis
A two-line solution is described in the answer above this one: https://mcmap.net/q/395177/-jackson-jsonnode-to-typed-collection You first need a reader, then you can read into your List. ObjectReader reader = mapper.readerFor(new TypeReference<List<String>>() { }); List<String> list = reader.readValue(arrayNode);Crescent
S
9

The ObjectMapper.convertValue() function is convenient and type-aware. It can perform a wide array of conversions between tree nodes and Java types/collections, and vice-versa.

An example of how you might use it:

List<String> list = new ArrayList<>();
list.add("one");
list.add("two");

Map<String,List<String>> hashMap = new HashMap<>();
hashMap.put("myList", list);

ObjectMapper mapper = new ObjectMapper();
ObjectNode objectNode = mapper.convertValue(hashMap, ObjectNode.class);
Map<String,List<String>> hashMap2 = mapper.convertValue(objectNode, new TypeReference<Map<String, List<String>>>() {});
Strongbox answered 14/3, 2018 at 21:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.