Deserialize JSON to Arraylist<Pojo> Using Jackson

Deserialize JSON to ArrayListPOJO using Jackson

You can deserialize directly to a list by using the TypeReference wrapper. An example method:

public static <T> T fromJSON(final TypeReference<T> type,
final String jsonPacket) {
T data = null;

try {
data = new ObjectMapper().readValue(jsonPacket, type);
} catch (Exception e) {
// Handle the problem
}
return data;
}

And is used thus:

final String json = "";
Set<POJO> properties = fromJSON(new TypeReference<Set<POJO>>() {}, json);

TypeReference Javadoc

How to use Jackson to deserialise an array of objects

First create a mapper :

import com.fasterxml.jackson.databind.ObjectMapper;// in play 2.3
ObjectMapper mapper = new ObjectMapper();

As Array:

MyClass[] myObjects = mapper.readValue(json, MyClass[].class);

As List:

List<MyClass> myObjects = mapper.readValue(jsonInput, new TypeReference<List<MyClass>>(){});

Another way to specify the List type:

List<MyClass> myObjects = mapper.readValue(jsonInput, mapper.getTypeFactory().constructCollectionType(List.class, MyClass.class));

Deserialize JSON array to a single Java object with Jackson

Thanks to bureaquete for suggestion to use custom Deserializer. But it was more suitable for me to register it with SimpleModule instead of @JsonDeserialize annotation. Below is complete JUnit test example:

@RunWith(JUnit4.class)
public class MapArrayToObjectTest {
private static ObjectMapper mapper;

@BeforeClass
public static void setUp() {
mapper = new ObjectMapper();
SimpleModule customModule = new SimpleModule("ExampleModule", new Version(0, 1, 0, null));
customModule.addDeserializer(Person.class, new PersonDeserializer());
mapper.registerModule(customModule);
}

@Test
public void wrapperDeserializationTest() throws IOException {
//language=JSON
final String inputJson = "{\"persons\": [[\"John\", \"Doe\"], [\"Jane\", \"Doe\"]]}";
PersonsListWrapper deserializedList = mapper.readValue(inputJson, PersonsListWrapper.class);
assertThat(deserializedList.persons.get(0).lastName, is(equalTo("Doe")));
assertThat(deserializedList.persons.get(1).firstName, is(equalTo("Jane")));
}

@Test
public void listDeserializationTest() throws IOException {
//language=JSON
final String inputJson = "[[\"John\", \"Doe\"], [\"Jane\", \"Doe\"]]";
List<Person> deserializedList = mapper.readValue(inputJson, mapper.getTypeFactory().constructCollectionType(List.class, Person.class));
assertThat(deserializedList.get(0).lastName, is(equalTo("Doe")));
assertThat(deserializedList.get(1).firstName, is(equalTo("Jane")));
}
}

class PersonsListWrapper {
public List<Person> persons;
}

class Person {
final String firstName;
final String lastName;

Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}

class PersonDeserializer extends JsonDeserializer<Person> {
@Override
public Person deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
JsonNode node = jp.readValueAsTree();
return new Person(node.get(0).getTextValue(), node.get(1).getTextValue());
}
}

Note that if you do not need wrapper object, you can deserialize JSON array
[["John", "Doe"], ["Jane", "Doe"]] directly to List<Person> using mapper as follows:

List<Person> deserializedList = mapper.readValue(inputJson, mapper.getTypeFactory().constructCollectionType(List.class, Person.class));

How to deserialize a json array followed by a normal property into a pojo in jackson. The array alone works

The solution is a deserializer, because the type handling is very difficult in this case. The deserializer decide between the two cases, array or the single last value, and call in the case of an array the deserializer for the CandleStick Class:

public class OhlcDeserializer extends JsonDeserializer<OhclPayload> {

@Override
public OhclPayload deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {

List<CandleStick> candleSticks = new ArrayList<CandleStick>();

Long last = null;

ObjectCodec objectCodec = p.getCodec();
JsonNode jsonNode = objectCodec.readTree(p);

Iterator<Entry<String, JsonNode>> payloadIterator = jsonNode.fields();
while (payloadIterator.hasNext()) {
Map.Entry<String, JsonNode> entry = payloadIterator.next();
if (entry.getKey().equals("last")) {
last = entry.getValue().asLong();
} else if (entry.getValue().isArray()) {
for (JsonNode node : entry.getValue()) {
CandleStick cs = p.getCodec().treeToValue(node, CandleStick.class);
candleSticks.add(cs);
}
}
}

return new OhclPayload(candleSticks, last);
}

}

I changed the OhclResponse to:

public class OhlcResponse extends Response<OhclPayload> {
}

And insert a OhlcPayload class for the deserializer:

@JsonDeserialize(using = OhlcDeserializer.class)
public class OhclPayload {

private List<CandleStick> candleSticks;

private Long last;
// getters and setters
}

Thats all.

Deserialize a json array to objects using Jackson and WebClient

For the response to be matched with AccountOrderList class, json has to be like this

{
"accountOrders": [
{
"symbol": "XRPETH",
"orderId": 12122,
"clientOrderId": "xxx",
"price": "0.00000000",
"origQty": "25.00000000",
"executedQty": "25.00000000",
"status": "FILLED",
"timeInForce": "GTC",
"type": "MARKET",
"side": "BUY",
"stopPrice": "0.00000000",
"icebergQty": "0.00000000",
"time": 1514558190255,
"isWorking": true
},
{
"symbol": "XRPETH",
"orderId": 1212,
"clientOrderId": "xxx",
"price": "0.00280000",
"origQty": "24.00000000",
"executedQty": "24.00000000",
"status": "FILLED",
"timeInForce": "GTC",
"type": "LIMIT",
"side": "SELL",
"stopPrice": "0.00000000",
"icebergQty": "0.00000000",
"time": 1514640491287,
"isWorking": true
},
....
]
}

This is what the error message says "out of START_ARRAY token"

If you cannot change the response, then change your code to accept Array like this

this.webClient.get().uri(payload).accept(MediaType.APPLICATION_JSON)
.retrieve().bodyToMono(AccountOrder[].class).log();

You can convert this array to List and then return.

JSON deserialize ArrayList correctly

First issue: you are deserializing to ArrayList without any generic type, because of this you are receiving ArrayList of LinkedHashMap. Jackson doesn't know that you are wanting list of person, so it uses LinkedHashMap as type applicable to any json.

To deserialize to list of person you should use:

ArrayList<Person> list = mapper.readValue(new FileInputStream("./person.json"),
mapper.getTypeFactory().constructCollectionType(ArrayList.class, Person.class));

Second issues: that you are working with Java 8 time (LocalDate class), but Jackson doesn't know about it. To be able to handle it properly, you need to add JavaTimeModule from jackson-datatype-jsr310 dependency and register it.

So resulting code will be like this:

public void write() {
ArrayList<Person> personList = new ArrayList<>();

Person p1 = new Person("James", "Bond", LocalDate.of(1997, 9, 22));
Person p2 = new Person("Santa", "Claus", LocalDate.of(1918, 11, 6));
Person p3 = new Person("Peter", "Griffin", LocalDate.of(1978, 3, 24));
Person p4 = new Person("Lois", "Griffin", LocalDate.of(1982, 7, 14));

personList.add(p1);
personList.add(p2);
personList.add(p3);
personList.add(p4);

ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());
ObjectWriter writer = mapper.writer(new DefaultPrettyPrinter());

try {
writer.writeValue(new File("./person.json"), personList);
} catch (IOException e) {
e.printStackTrace();
}
}

public void read() {
ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());

try {
ArrayList<Person> list = mapper.readValue(new FileInputStream("./person.json"),
mapper.getTypeFactory().constructCollectionType(ArrayList.class, Person.class));
System.out.println("Read: " + list.get(0).getFirstname());
} catch (IOException e) {
e.printStackTrace();
}

}

Map JsonArray to ListPojo using Jackson ObjectMapper

You can use the TypeFactory to create a CollectionLikeType.
For example like this:

ObjectMapper objectMapper = new ObjectMapper();

CollectionLikeType collectionLikeType = objectMapper.getTypeFactory()
.constructCollectionLikeType(List.class, String.class);

List<String> o = objectMapper.readValue("[\"hello\"]", collectionLikeType);

assertEquals(o, List.of("hello"));


Related Topics



Leave a reply



Submit