How to Parse a JSON String to an Array Using Jackson

How to parse a JSON string to an array using Jackson

I finally got it:

ObjectMapper objectMapper = new ObjectMapper();
TypeFactory typeFactory = objectMapper.getTypeFactory();
List<SomeClass> someClassList = objectMapper.readValue(jsonString, typeFactory.constructCollectionType(List.class, SomeClass.class));

How to parse a JSON array of objects using Jackson?

The Employee POJO should look like this:

@JsonProperty("id")
private final List<String> ids;
@JsonProperty("firstname")
private final List<String> firstNames;
@JsonProperty("lastname")
private final List<String> lastNames;

@JsonCreator
public Employee(@JsonProperty(value = "id") List<String> ids, @JsonProperty(value = "firstname") List<String> firstNames, @JsonProperty(value = "lastname") List<String> lastNames) {
this.ids = ids;
this.firstNames = firstNames;
this.lastNames = lastNames;
}

//getters code

Then, you have an object Data:

@JsonProperty("date")
private final String date;
@JsonProperty("employee")
private final List<Employee> employees;

@JsonCreator
public Data(@JsonProperty(value = "date") String date, @JsonProperty(value = "employee") List<Employee> employees) {
this.date = date;
this.employees = employees;
}

//getters code

Finally, the whole Answer that you want to parse has this shape:

@JsonProperty("data")
private final Data data;

@JsonCreator
public Answer(@JsonProperty(value = "data") Data data) {
this.data = data;
}

//getter code

Once you have defined these 3 classes, then you will be able to do:

ObjectMapper objectMapper = new ObjectMapper();
Answer answer = objectMapper.readValue(yourStringAnswer, Answer.class);

Note: in your question, you are trying to parse an URL to an ObjectNode. I hardly doubt you would be able to do that.
I guess you want to perform the HTTP request to the URL, then getting the response stream and that's what you want to parse into Answer (not the URL itself).

Also, a few notes on the API response (in case you own it and so you can act on it):

  • All the lists would be more naturally declared with a plural name (e.g. employee should be employees)
  • The list of ids are numeric but are returned as strings. Also, why an employee would have a list of ids, and not a single id?
  • Why would an employee have a list of first names and last names? Shouldn't this be a simple string each (even if composed by more than one name)?
  • Use camel case (firstName, not firstname)
  • I don't see the point of putting everything into data, it may simply be the response containing date and employees

How to parse a JSON array of strings?

You can use the ObjectMapper.readValue() method with a TypeReference to get a list of strings:

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.util.List;

public class Test {
public static void main(String[] args) throws IOException {
String json = "[\"UUID\",\"UUID\"]";
ObjectMapper mapper = new ObjectMapper();
List<String> values = mapper.readValue(json,
new TypeReference<List<String>>() {});
}
}

Or you can use the ObjectMapper.readValue() method with the String[].class to get an array of strings:

import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;

public class Test {
public static void main(String[] args) throws IOException {
String json = "[\"UUID\",\"UUID\"]";
ObjectMapper mapper = new ObjectMapper();
String[] values = mapper.readValue(json, String[].class);
}
}

java jackson parse json array

The core issue is that you receive an array of arrays where you expect and array of objects. Changing mapper.readValue(response.getBody(), KlineResponse.class) to mapper.readValue(response.getBody(), Object[].class) confirms it.

You have a couple of options on how to proceed:

  1. Change from Jackson to standard JSON parsing, as suggested by @cricket_007 on his answer
  2. Instead of mapping it to an object try to access the JSON differently. See @jschnasse's answer for an example.
  3. Change the format of text you parse, if you can
  4. If you can't change the format of the input then you can either

    • Create a constructor and annotate it with @JsonCreator, like instructed here
    • Parse the input as Object array and feed the parsed array into a constructor of your own

Java; Jackson; Parsing the array of array json string

You don't need to Result class, it is redundant. You need to parse it as List<List<Student>> because your json structure starts as array and contains another arrays.

Here is how you can parse your :

ObjectMapper mapper = new ObjectMapper();
try {
List<Result> responseList = mapper.readValue(
Files.readAllBytes(Paths.get("test.json")),
new TypeReference<List<List<Student>>>() {});

} catch (IOException e) {
e.printStackTrace();
}

Output :

Sample Image

How to parse raw values from JSON array items with Jackson?

You can convert the payload to com.fasterxml.jackson.databind.node.ArrayNode and then iterate through elements (JsonNode in this case) and add them to a List<String> (which you can then convert to String[] if you want).

One thing to be aware of - the formatting will not be as you expect. JsonNode has two methods - toString() which deletes all the white space and toPrettyString which adds whitespaces and newlines to the final String

        String payload = """ 
[
{"a": 1, "b": "hello"},
{"a": 2, "b": "bye"},
"something"
]
""";
ArrayNode items = new ObjectMapper().readValue(payload, ArrayNode.class);

List<String> rawItemsList = new ArrayList<>();

for (JsonNode jsonNode : items) {
rawItemsList.add(jsonNode.toString());
}

// You can just keep using the rawItemsList, but I've converted it to array since the question mentioned it
String[] rawItemsArr = rawItemsList.toArray(new String[0]);

assertEquals("""
{"a":1,"b":"hello"}""", rawItemsArr[0]);
assertEquals("""
{"a":2,"b":"bye"}""", rawItemsArr[1]);
assertEquals("\"something\"", rawItemsArr[2]);


Related Topics



Leave a reply



Submit