Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Incrementally binding JSON objects in an array (list) using Jackson.
package tv.xrm.test;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.*;
public class JacksonStreamingBindingTest {
public static void main(String[] args) throws Exception {
final String jsonList = generateListOfJsonObjects();
final TypeReference<Map<String, String>> typeRef = new TypeReference<Map<String, String>>() {
};
/* This works for a "wrapped" sequence of objects, i.e. a JSON array. Using
ObjectMapper.readValues(JsonParser, ...) will NOT work for an array, as
that assumes a non-wrapped sequence of values. See source of MappingIterator.
*/
Iterator<Map<String, String>> it = new ObjectMapper().reader(typeRef).readValues(jsonList);
while (it.hasNext()) {
Map<String, String> map = it.next();
System.out.println(map);
}
}
/**
* A quick & dirty method to generate a long JSON list of somewhat random objects.
*/
private static String generateListOfJsonObjects() throws Exception {
final int length = 1000;
final Random r = new Random();
List<Map<String, String>> result = new ArrayList<>(length);
for (int i = 0; i < length; i++) {
Map<String, String> map = new HashMap<>();
for (int j = 0; j < 3; j++) {
map.put("key" + r.nextInt(), "value" + r.nextInt());
}
result.add(map);
}
return (new ObjectMapper()).writeValueAsString(result);
}
}
package tv.xrm.test;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.*;
/**
* Just a test of "manually" mixing Jackson's streaming and data binding modes. This kind of approach works
* for any arbitrary JSON structure.
*
* @see com.fasterxml.jackson.databind.ObjectMapper#readValues(com.fasterxml.jackson.core.JsonParser, com.fasterxml.jackson.core.type.TypeReference)
*
*/
public class JacksonStreamingBindingTest2 {
interface Processor<T> {
void process(T object);
}
public static void main(String[] args) throws Exception {
final String jsonList = generateListOfJsonObjects();
JsonParser jp = new ObjectMapper().getFactory().createParser(jsonList);
final TypeReference<Map<String, String>> typeRef = new TypeReference<Map<String, String>>() {
};
bindListElementsIteratively(jp, typeRef, new Processor<Map<String, String>>() {
@Override
public void process(Map<String, String> stringStringMap) {
System.out.println(stringStringMap);
}
});
}
/**
* Parse list incrementally by binding each list element after the other, using a callback for processing.
*/
private static <T> void bindListElementsIteratively(JsonParser jp, TypeReference<T> typeRef, Processor<T> func) throws IOException {
try {
if (jp.nextToken() != JsonToken.START_ARRAY) {
throw new IOException("expected data to start with an array");
}
JsonToken current = jp.nextToken();
while (current != null && current != JsonToken.END_ARRAY) {
if (current.isStructStart()) {
final T mapped = jp.readValueAs(typeRef);
func.process(mapped);
}
current = jp.nextToken();
}
} finally {
jp.close();
}
}
/**
* A quick & dirty method to generate a long JSON list of somewhat random objects.
*/
private static String generateListOfJsonObjects() throws Exception {
final int length = 1000;
final Random r = new Random();
List<Map<String, String>> result = new ArrayList<>(length);
for (int i = 0; i < length; i++) {
Map<String, String> map = new HashMap<>();
for (int j = 0; j < 3; j++) {
map.put("key" + r.nextInt(), "value" + r.nextInt());
}
result.add(map);
}
return (new ObjectMapper()).writeValueAsString(result);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment