简体   繁体   中英

Convert a JSON array to a HashMap<String,Object> using jackson parser

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).

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;
}

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM