我有一个大的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没有默认构造函数的错误。)
这是实现我想要做的正确方法吗?有谁知道为什么我收到此错误消息?
答案 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没有默认构造函数的错误。)
这可能是因为无法访问您的构造函数。例如,您的反序列化器被实现为非静态内部类。