1

I am using : import com.fasterxml.jackson.databind.*

I have a json array :

{"nodes":
    [
     {"blockId":"decision1422461296135","text":"hello"},  
     {"blockId":"Action1422461296640","text":"Action"},  
     {"blockId":"prompt1422461298089","text":"Prompt"}
    ]
}

I want to convert the above array to a HashMap< String,Node > , where the key is the blockId and Node is a POJO with id and text fields in it.

I would rather not use any other external library.

Right now I am converting the JSON array to an Array of Nodes and then iterating through the array to create the HashMap I want. I don't think this is optimized. I want to create the HashMap when the ObjectMapper parses the JSON (so just 1 pass through the JSON array).

5
  • Have you measured a performance problem? What size is your array? Pre-optimization is the root of all evil. Do the simple thing, and optimize only if you have a performance problem and have proven it came from this part of the code. My guess is that transforming the array in memoty into a map is peanuts compared to actually reading the JSON. Commented Apr 20, 2015 at 5:04
  • I want to optimize this particular piece of code irrespective of the size of the array. Lets assume this is an interview question and you are asked to optimizing the conversion. Is there a way to do this via jackson (maybe using jackson annotations). Commented Apr 20, 2015 at 5:06
  • My answer to the interview would be: optimizing if there is no need to is a waste of time, money and energy, and has a very good chance of producing more complex, buggier, harder to maintain code. For the good of the company and the product, I'd not do anything unless there is a performance problem, and I've measures it came from transforming the array into a map. Commented Apr 20, 2015 at 5:10
  • The short of it is : Forget about optimization, I just want to achieve what is asked in the question. Commented Apr 20, 2015 at 5:58
  • You can do what you are already doing in a custom deserializer. If there is any other annotation to do what you want, it would do the same: read node, put node to HashMap properly, gather the next node. The performance would be the same. Check this documentation for more information about custom deserializers. Commented Apr 20, 2015 at 8:51

2 Answers 2

1

Can you change the JSON structure as follows:

{    
 "decision1422461296135":{"text":"hello"},  
 "Action1422461296640":  {"text":"Action"},  
 "prompt1422461298089":  {"text":"Prompt"}
}

And the Nodes class can look something like below:

public class Nodes {
    private Map<String,Node> nodesMap;
}
Sign up to request clarification or add additional context in comments.

1 Comment

This is a good suggestion. I would rather not change the json structure.
0

After digging around Jackson serializer internals, here is the version you want:

@JsonDeserialize(using = NodeDeserializer.class)
public class Nodes {
    private Map<String, Node> nodesMap;
    //getter/setter
}

Serializer:

public class NodeDeserializer extends JsonDeserializer<Nodes> {
    @Override
    public Nodes deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        Map<String, Node> nodes = new HashMap<>();
        p.getCurrentToken();//START_OBJECT
        p.nextToken();//FIELD_NAME
        p.nextToken();//START_ARRAY
        p.nextToken();//START_OBJECT
        while (p.getCurrentToken() != JsonToken.END_ARRAY) {
            p.nextToken();//blockId field
            p.nextToken();//blockId value
            String id = p.getValueAsString();
            p.nextToken();//text field
            p.nextToken();//text value
            String text = p.getValueAsString();
            p.nextToken();//END_OBJECT
            p.nextToken();//START_OBJECT?
            nodes.put(id, new Node().setBlockId(id).setText(text));
        }
        return new Nodes().setNodesMap(nodes);
    }
}

This should cover your request. Instead of BeanDeserializer, this class is evaluated and it only iterates once.

For a valid json, it works fine. I tried it with Jackson 2.5.2

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.