简体   繁体   English

杰克逊定制解串器在阅读列表时创建空的pojo

[英]Jackson custom deserializers creating empty pojo when reading list

I have the following json 我有以下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. 我想用持久层中的项目替换myReferenceObject

I followed JacksonHowToCustomDeserializers 我关注了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. 一切都能正确调试,但是生成的myListC列表的对象数量增加了一倍,偶数保持正确的对象以及正确的myReferenceObject而不具有持久性(使用我的模块正确反序列化),而奇数元素保持空的Pojos,即对象为null所有变量的值。

Through debug, It never reaches return null in my custom deserializer, for it works properly each time its executed. 通过调试,它在我的自定义反序列化器中永远不会达到return null,因为它每次执行时都能正常工作。 The issue seems to be further up stream where it inserts blank myListC objects. 问题似乎更进一步,它会插入空白的myListC对象。

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). 您想循环直到到达对象的末尾,但是用返回b(如果是块)中断循环。 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. 如果您可以从杰克逊更改,也可以看看Genson http://code.google.com/p/genson/ 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): 这是解决genson问题的方法(对于本示例,它与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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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