Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How the Order of setter method call of POJO is determined in jackson while De-serializing Json?

Tags:

java

json

jackson

I have a json like

{
    "key" : ["key1", "key2", "key3"],
    "value" : "v1";
}

I am De-serializing it to my Pojoclass using jackson, While De-serializing I want variable value to be type of List<String> whose size will depend on the size of variable key. So that final object will represent this Json.

{
     "key" : ["key1", "key2", "key3"],
     "value" : ["v1", "v1", "v1"];
}

So far my Pojo class is like this

public class Pojo {

@JsonProperty("key")
private List<String> key;
@JsonProperty("value")
private List<String> value;

@JsonProperty("key")
public List<String> getKey() {
    return key;
}

@JsonProperty("key")
public void setKey(List<String> key) {
    this.key = key;
}

@JsonProperty("value")
public List<String> getValue() {
    return value;
}

@JsonProperty("value")
public void setValue(String val) {
    List<String> arr = new ArrayList<String>();
    for (int i=0; i<key.size(); i++) {
        arr.add(val);
    }
    this.value = arr;
}

}

but I am getting JsonMappingException. While debugging I found that inside the setValue method variable key is null. Is there a way to set the value of variable key first?( before variable value)

like image 432
Anurag Tripathi Avatar asked Oct 03 '13 09:10

Anurag Tripathi


1 Answers

You should hide this ugly conversion in custom deserializer class. It could look like this:

class PojoJsonDeserializer extends JsonDeserializer<Pojo> {

    @Override
    public Pojo deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        InnerPojo innerPojo = jp.readValueAs(InnerPojo.class);

        return innerPojo.toPojo();
    }

    private static class InnerPojo {
        public List<String> key;
        public String value;

        Pojo toPojo() {
            Pojo pojo = new Pojo();
            pojo.setKey(new ArrayList<String>(key));
            pojo.setValue(valueNTimes(value, key.size()));

            return pojo;
        }

        private List<String> valueNTimes(String value, int nTimes) {
            List<String> result = new ArrayList<String>(nTimes);
            for (int index = 0; index < nTimes; index++) {
                result.add(value);
            }

            return result;
        }
    }
}

Your POJO class could look "natural" now:

@JsonDeserialize(using = PojoJsonDeserializer.class)
class Pojo {

    private List<String> key;
    private List<String> value;

    public List<String> getKey() {
        return key;
    }

    public void setKey(List<String> key) {
        this.key = key;
    }

    public List<String> getValue() {
        return value;
    }

    public void setValue(List<String> value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "Pojo [key=" + key + ", value=" + value + "]";
    }
}

Simple test program:

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

public class JacksonProgram {

    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        System.out.println(mapper.readValue(json, Pojo.class));
    }
}

prints:

Pojo [key=[key1, key2, key3], value=[v1, v1, v1]]
like image 79
Michał Ziober Avatar answered Oct 16 '22 22:10

Michał Ziober