自定义杰克逊反序列化器省略某些对象的映射

时间:2016-06-24 13:22:44

标签: java json jackson deserialization

我有一个大的JSON文件,它由我映射到POJO的结构组成,然后存储在Collection中。结构类似于:

[
{
    "id": 1234,
    "file": "C:\\Programs\\Program1.exe",
    "exists": true
}
{
    "id": 5678,
    "file": "C:\\Programs\\Program2.exe",
    "exists": false
}
...
]

使用Jackson流API我已经读取了所有这些结构,并且POJO已成功存储在Collection中。我的POJO类看起来像这样:

public class Programs
{
    @JsonProperty("id")
    private Integer id;

    @JsonProperty("file")
    private String file;

    @JsonProperty("exists")
    private Boolean exists;

    @JsonGetter("id")
    public Integer getId()
    {
      return id;
    }

    @JsonGetter("file")
    public String getFile()
    {
      return file;
    }

    @JsonGetter("exists")
    public Boolean getExists()
    {
      return exists;
    }
}

但是,我想省略在反序列化过程中"exists"设置为false的任何结构,以便不会为它们创建任何POJO。所以我在这个SO问题[How do I call the default deserializer from a custom deserializer in Jackson]的帮助下编写了一个自定义反序列化器,我的重写deserialize看起来像:

@Override
public Programs deserialize(JsonParser parser, DeserializationContext context)
   throws IOException
{
    Programs programs = (Programs)defaultDeserializer.deserialize(parser, context);

    if (!programs.getExists())
    {
        throw context.mappingException("[exists] value is false.");
    }
    return programs;
}

但是,当我运行一些单元测试时,我收到以下错误:

"Can not deserialize instance of java.util.ArrayList out of START_OBJECT token"
message was "Class com.myprogram.serializer.ProgramsJsonDeserializer
has no default (no arg) constructor"

(添加no arg构造函数会出现StdDeserializer没有默认构造函数的错误。)

这是实现我想要做的正确方法吗?有谁知道为什么我收到此错误消息?

1 个答案:

答案 0 :(得分:1)

  

我想省略任何将“exists”设置为false的结构   反序列化过程,以便不为它们创建任何POJO。

我认为您的目标是检索一个Programs实例的列表,该实例在去除邮件后只有exists设置为true。用于过滤这些不需要的实例的自定义CollectionDeserializer可能有所帮助:

public class ProgramsCollectionHandler extends SimpleModule {
    private static class ProgramsCollectionDeserializer extends CollectionDeserializer {

        public ProgramsCollectionDeserializer(CollectionDeserializer deserializer) {
            super(deserializer);
        }

        private static final long serialVersionUID = 1L;

        @Override
        public Collection<Object> deserialize(JsonParser parser, DeserializationContext context)
                throws IOException, JsonProcessingException {
            Collection<Object> result = super.deserialize(parser, context);
            Collection<Object> filteredResult = new ArrayList<Object>();
            for (Object o : result) {
                if (o instanceof Programs) {
                    final Programs programs = (Programs) o;
                    if (programs.exists) {
                        filteredResult.add(programs);
                    }
                }
            }
            return filteredResult;
        }

        @Override
        public CollectionDeserializer createContextual(
                DeserializationContext context,
                BeanProperty property) throws JsonMappingException {
            return new ProgramsCollectionDeserializer(super.createContextual(context, property));
        }
    }

    private static final long serialVersionUID = 1L;

    @Override
    public void setupModule(Module.SetupContext context) {
        super.setupModule(context);
        context.addBeanDeserializerModifier(new BeanDeserializerModifier() {
            @Override
            public JsonDeserializer<?> modifyCollectionDeserializer(
                    DeserializationConfig config, CollectionType type,
                    BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
                if (deserializer instanceof CollectionDeserializer) {
                    return new ProgramsCollectionDeserializer(
                            (CollectionDeserializer) deserializer);
                } else {
                    return super.modifyCollectionDeserializer(config, type, beanDesc,
                            deserializer);
                }
            }
        });
    }
}

之后,您可以将其注册到对象映射器中:

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new ProgramsCollectionHandler());
  

“无法反序列化java.util.ArrayList的实例   START_OBJECT令牌“消息是”类   com.myprogram.serializer.ProgramsJsonDeserializer没有默认值(没有   arg)构造函数“   (添加no arg构造函数会给出StdDeserializer没有默认构造函数的错误。)

这可能是因为无法访问您的构造函数。例如,您的反序列化器被实现为非静态内部类。