简体   繁体   中英

Jackson custom deserializers creating empty pojo when reading list

I have the following json

{
"id":null,
"name":"Myapp",
"description":"application",
"myListA":["java.util.ArrayList",[{
    "id":50,
    "name":"nameA1",
    "myListB":{
        "id":48,
        "name":"nameB1",
        "myListC":["java.util.ArrayList",[{
            "id":1250,
            "name":"nameC1",
            "description":"nameC1_desc",
            "myReferenceObject":{
                "code":"someCodeA"
            }
        },{
            "id":1251,
            "name":"nameC2",
            "description":"nameC1_desc",
            "myReferenceObject":{
                "code":"someCodeB"
            }

and so on.

I i wish to replace myReferenceObject with an item from persistence layer.

I followed JacksonHowToCustomDeserializers

My deserializer is as follows:

public class MyReferenceObjectCodeDeserializer extends JsonDeserializer<MyReferenceObjectBean> {

    @Override
    public ColumnReferenceBean deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {

        while (jp.nextToken() != JsonToken.END_OBJECT) {
            String fieldname = jp.getCurrentName();
            jp.nextToken();
            if ("code".equalsIgnoreCase(fieldname)) {
                MyReferenceObjectBean b = MyReferenceObjectServiceImpl.retrieveByCode(jp.getText());
                logger.info("returning " +b.toString());
                return b;
            }
        }
        logger.info("returning null");
        return null;
    }
}

And I attache the module like so:

ObjectMapper mapper = new ObjectMapper();
    mapper.enableDefaultTyping();
    SimpleModule module = new SimpleModule("myModule", new Version(1, 0, 0, null));
    module.addDeserializer(MyReferenceObjectBean.class, new MyReferenceObjectCodeDeserializer());

    mapper.registerModule(module);
    try {
        return mapper.readValue(serializedJsonString, MyMainObjectBean.class);
    } catch (IOException e) {
        logger.error("Unable to parse=" + serializedJsonString, e);
    }

everything debugs correctly however the resulting myListC list has double the amount of objects with even numbers holding the correct objects along with the correct myReferenceObject out of persistence (deserialized correctly using my module) and the odd elements holding empty Pojos, that is an object with null values for all variables.

Through debug, It never reaches return null in my custom deserializer, for it works properly each time its executed. The issue seems to be further up stream where it inserts blank myListC objects.

Any help would greeatly be appreciated.

Thanks!

There is a logic problem in your code. You want to loop until you reach the end of the object but break your loop with return b (if block). This means that you will not read the object stream until its end.

Try something like this (didn't try it but should work).

public class MyReferenceObjectCodeDeserializer extends JsonDeserializer<MyReferenceObjectBean> {

@Override
public ColumnReferenceBean deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
    MyReferenceObjectBean b = null;
    while (jp.nextToken() != JsonToken.END_OBJECT) {
        String fieldname = jp.getCurrentName();
        jp.nextToken();
        if ("code".equalsIgnoreCase(fieldname)) {
          b = MyReferenceObjectServiceImpl.retrieveByCode(jp.getText());
          logger.info("returning " +b.toString());
        }
    }
    if (b==null) logger.info("returning null");
    return b;
}
}

You can also have a look at Genson http://code.google.com/p/genson/ if you can change from jackson. In addition of some other features it is supposed to be easier to use. Here is how you can solve your problem with genson (for this example it is quite similar to jackson):

public class MyReferenceObjectCodeDeserializer implements Deserializer<MyReferenceObjectBean> {

public MyReferenceObjectBeandeserialize(ObjectReader reader, Context ctx) throws TransformationException, IOException {
        MyReferenceObjectBean b = null;
        reader.beginObject();
        while (reader.hasNext()) {
            reader.next();
            if ("code".equalsIgnoreCase(reader.name()))
                b = MyReferenceObjectServiceImpl.retrieveByCode(reader.valueAsString());
        }
        reader.endObject();
        return b;
    }
}

// register it
Genson genson = new Genson.Builder().withDeserializers(new MyReferenceObjectCodeDeserializer()).create();
MyClass myClass = genson.deserialize(json, MyClass.class);

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