Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parsing an array of JSON objects using Jackson 2.0

I am in the process of upgrading Jackson from 1.9.4 to 2.2.0. The transition has been smooth, except I can't seem to get array parsing for Objects working. In 1.9.4 I could do this:

private List<Subjects> mSubjects;
mSubjects = objectMapper.readValue(subjectsJsonArrayNode, new TypeReference<List<Subjects>>() {});

With Jackson 2.2.0, I get a "cannot resolve method" compile-time error. Jackson's ObjectMapper header file for 1.9.4 contains these readValue methods for JsonNodes:

public <T> T readValue(JsonNode root, java.lang.Class<T> valueType)
public <T> T readValue(JsonNode root, org.codehaus.jackson.type.TypeReference valueTypeRef)
public <T> T readValue(JsonNode root, org.codehaus.jackson.type.JavaType valueType)

And Jackson 2.2.0's header file:

public <T> T readValue(JsonParser jsonParser, java.lang.Class<T> tClass)
public <T> T readValue(JsonParser jsonParser, com.fasterxml.jackson.core.type.TypeReference<?> typeReference)
public final <T> T readValue(JsonParser jsonParser, com.fasterxml.jackson.core.type.ResolvedType resolvedType)
public <T> T readValue(JsonParser jsonParser, com.fasterxml.jackson.databind.JavaType javaType) 

So I need to switch from passing a JsonNode to a JsonParser, but I'm not quite sure how to make that transition. That said, I'm not sure if I'm even going down the right path because JsonParser is defined as an abstract class so I can't even easily initialize an instance to play around with it.

For those who come without an answer, here is a temporary solution I have in place where I iterate and manually parse each object:

 private List<Subjects> mSubjects = new ArrayList<Subjects>();
 for(JsonNode subjectJsonNode : subjectsJsonArrayNode) {
    mSubjects.add(objectMapper.treeToValue(subjectJsonNode, Subject.class));
 }
like image 636
Mark Avatar asked Jul 05 '13 19:07

Mark


2 Answers

You can simply call the JsonNode.traverse() method to get the JsonParser.

Tested with the following simple example:

public class App {

    public static class Foo {
        public int foo;
    }

    public static void main(String[] args) {

        String json = "{\"someArray\":[{\"foo\":5},{\"foo\":6},{\"foo\":7}]}";
        ObjectMapper mapper = new ObjectMapper();
        JsonNode node = mapper.readTree(json);
        node = node.get("someArray");
        TypeReference<List<Foo>> typeRef = new TypeReference<List<Foo>>(){};
        List<Foo> list = mapper.readValue(node.traverse(), typeRef);
        for (Foo f : list) {
            System.out.println(f.foo);
        }
    }
}

outputs:

5
6
7

like image 136
Brian Roach Avatar answered Sep 19 '22 09:09

Brian Roach


I use this method for lists:

/**
 * Returns a list collection of any specified type
 * @param jsonValue the json string content to deserialize
 * @param type the type to serialize into
 * @return a list of specified type
 */
public List<?> readJSONToList(String jsonValue,Class<?> type){

    List<?> objDTOS=null;
    try {
        //get json content without root name
        JsonNode root= objectMapper.readTree(jsonValue).get(getRootName());
        TypeFactory tf = objectMapper.getTypeFactory();
        JavaType listOfObjs = tf.constructCollectionType(ArrayList.class,type);
        objDTOS=objectMapper.readValue(root.traverse(), listOfObjs);

    } catch (NullPointerException e) {
        Logger.write("Jackson Json List Reader", e.getMessage(), Logger.ERROR);
    } catch (JsonParseException e) {    
        Logger.write("Jackson Json List Reader", e.getMessage(), Logger.ERROR);
    } catch (IOException e) {
        Logger.write("Jackson Json List Reader", e.getMessage(), Logger.ERROR);
    }
    return  objDTOS;
}
like image 25
Maxrunner Avatar answered Sep 21 '22 09:09

Maxrunner