[英]Custom deserializer for any list in Jackson
I have a problem with wrong objects in lists. 我有清单中错误对象的问题。 For instance I've a JSON model:
例如,我有一个JSON模型:
{
"items": [
{
"id": 1,
"name": "Item1"
},
{
"id": 2,
"name": "Item2"
},
{
"id": [],
"name": "Item3"
}
]
}
and two POJO 和两个POJO
data class BadList(val items: List<BadItem>)
data class BadItem(val id: Int, val name: String)
Of course, when the parser stumbles upon a third element I get the exception 当然,当解析器偶然发现第三个元素时,我得到了异常
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.Integer out of START_ARRAY token
at [Source: {"items":[{"id":1,"name":"Item1"},{"id":2,"name":"Item2"},{"id":[],"name":"Item3"}]}; line: 1, column: 19] (through reference chain: my.package.BadList["items"]->java.util.ArrayList[2]->my.package.BadItem["id"])
Who knows how to get around this? 谁知道如何解决这个问题? I want to skip that wrong item.
我想跳过那个错误的项目。
You can write a custom deserializer
and implement deserialization logic in it, eg: 您可以编写自定义
deserializer
并在其中实现反序列化逻辑,例如:
class ItemIdDeserialiser extends JsonDeserializer<Integer> {
@Override
public Integer deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
Object value = p.getCurrentValue();
//Check if it's Integer
if(value instanceof Integer){
return (Integer) value;
}
return null; //Or return first element if it's a non empty list
}
}
Once this is done, you can annotate the field with @JsonDeserialise
to instruct jackson to use your class, eg: 完成此操作后,您可以使用
@JsonDeserialise
对该字段进行注释,以指示jackson使用您的课程,例如:
class Item {
@JsonDeserialize(using = ItemIdDeserialiser.class)
private Integer id;
}
Update 更新资料
If you just want to ignore the field in serialization/deserialization then you can annotate it with @JsonIgnore
, eg 如果只想忽略序列化/反序列化中的字段,则可以使用
@JsonIgnore
对其进行@JsonIgnore
,例如
class Item {
@JsonIgnore
private Integer id;
}
Or even better, remove id
from pojo and add @JsonIgnoreProperties
on the class, eg: 甚至更好的是,从pojo中删除
id
并在类上添加@JsonIgnoreProperties
,例如:
@JsonIgnoreProperties(ignoreUnknown = true)
class Item {
}
It will automatically ignore the properties which are present in json
but not found in class. 它将自动忽略
json
中存在但类中找不到的属性。
You can use a "HidableSerializer" for this and check the data during serialization 您可以为此使用“ HidableSerializer”并在序列化期间检查数据
1. Create a IHidable interface 1.创建一个IHidable接口
The interface has a isHidden method which is called during serialization 该接口具有isHidden方法,该方法在序列化过程中被调用
package ch.hasselba.jackson.test;
public interface IHidable {
public boolean isHidden();
}
2. Change your BadItem class 2.更改您的BadItem类
Add the interface and change the setter of id . 添加接口并更改id的设置器。 When property id is deserialized, it is tested if it is an Integer.
反序列化属性ID时 ,将测试它是否为Integer。 If not, the item is marked as bad.
如果不是,则将该项目标记为不良。
package ch.hasselba.jackson.test;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties( {"hidden"} )
public class BadItem implements IHidable{
private Integer id;
public String name;
private boolean isBadItem;
public Integer getId(){
return id;
}
public void setId(Object value){
if( value instanceof Integer ){
this.id = (Integer) value;
}else{
this.isBadItem = true;
}
}
public boolean isHidden() {
return isBadItem;
}
}
3. Create a HidableSerializer 3.创建一个HidableSerializer
package ch.hasselba.jackson.test;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
@SuppressWarnings("serial")
public class HidableSerializer<T> extends StdSerializer<T> {
private JsonSerializer<T> defaultSerializer;
protected HidableSerializer(Class<T> t) {
super(t);
}
public JsonSerializer<T> getDefaultSerializer() {
return defaultSerializer;
}
public void setDefaultSerializer(JsonSerializer<T> defaultSerializer) {
this.defaultSerializer = defaultSerializer;
}
@Override
public void serialize(T value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException {
if( value instanceof IHidable ){
IHidable hidableValue = (IHidable) value;
if( hidableValue.isHidden() )
return;
}
defaultSerializer.serialize(value, jgen, provider);
}
}
4. Register the HidableSerializer and that's it 4.注册HidableSerializer就是这样
package ch.hasselba.jackson.test;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
public class Demo {
@SuppressWarnings("serial")
public static void main(String[] args) {
// register the HidableSerializer
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(Include.NON_EMPTY);
mapper.registerModule(new SimpleModule() {
@Override
public void setupModule(SetupContext context) {
super.setupModule(context);
context.addBeanSerializerModifier(new BeanSerializerModifier() {
@Override
public JsonSerializer<?> modifySerializer(
SerializationConfig config, BeanDescription desc, JsonSerializer<?> serializer) {
if (BadItem.class.isAssignableFrom(desc.getBeanClass())) {
HidableSerializer ser = new HidableSerializer(BadItem.class);
ser.setDefaultSerializer(serializer);
return ser;
}
return serializer;
}
});
}
});
String content = "{ \"items\": [ { \"id\": 1, \"name\": \"Item1\" }, { \"id\": 2, \"name\": \"Item2\" }, { \"id\":[], \"name\": \"Item3\" } ]}";
// build the Object
BadList test = null;
try {
test = mapper.readValue(content, BadList.class);
} catch (Exception e) {
e.printStackTrace();
}
// and now convert it back to a String
String data = null;
try {
data = mapper.writeValueAsString(test);
} catch (Exception e) {
e.printStackTrace();
}
// print the result
System.out.println( data );
}
}
When changing the id "[]" to an Integer value, the Item is displayed, otherwise it is empty. 将id“ []”更改为Integer值时,将显示该项目,否则为空。
The result: 结果:
{"items":[{"id":1,"name":"Item1"},{"id":2,"name":"Item2"}]}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.