[英]Enable Jackson Deserialization of Empty Objects to Null
我被要求更改我們的 jackson 映射配置,以便我們反序列化(來自 JSON)的每個空 object 將被反序列化為 null。
問題是我正在努力去做,但沒有任何運氣。 這是我們的ObjectMapper
配置示例(和示例):
ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, true);
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ISO_DATE_TIME));
javaTimeModule.addDeserializer(Instant.class, InstantDeserializer.INSTANT);
mapper.registerModule(javaTimeModule);
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
warmupMapper(mapper);
return mapper;
我想過要添加:
mapper.configure(
DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
但它只適用於字符串。
恐怕使用自定義解串器對我沒有幫助,因為我正在編寫一個通用(針對所有對象)映射器。 所以我可能需要像委托人或后處理反序列化方法這樣的東西。
因此,對於像""
或{}
這樣的 json,我希望在 java 中轉換為null
(而不是空字符串或Object
實例)。
什么是你的空對象? 具有空值字段的對象? 一個沒有字段的對象? 您可以創建一個自定義來檢查節點並反序列化您想要的方式。 我認為以通用方式使用它沒有問題。
我做了一個小例子:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import java.io.IOException;
import java.util.Objects;
public class DeserializerExample<T> extends StdDeserializer<T> {
private final ObjectMapper defaultMapper;
public DeserializerExample(Class<T> clazz) {
super(clazz);
defaultMapper = new ObjectMapper();
}
@Override
public T deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException {
System.out.println("Deserializing...");
JsonNode node = jp.getCodec().readTree(jp);
for (JsonNode jsonNode : node) {
if (!jsonNode.isNull()) {
return defaultMapper.treeToValue(node, (Class<T>) getValueClass());
}
}
return null;
}
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(Person.class, new DeserializerExample(Person.class));
mapper.registerModule(module);
Person person = mapper.readValue("{\"id\":1, \"name\":\"Joseph\"}", Person.class);
Person nullPerson = mapper.readValue("{\"id\":null, \"name\":null}", Person.class);
System.out.println("Is null: " + Objects.isNull(person));
System.out.println("Is null: " + Objects.isNull(nullPerson));
}
}
我有同樣的問題。
我有一個City
類,有時我會從網絡服務請求中收到'city':{}
。
因此,標准序列化程序會創建一個全為空字段的新城市。
我以這種方式創建了一個自定義解串器
public class CityJsonDeSerializer extends StdDeserializer<City> {
@Override
public City deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException {
JsonNode node = jp.getCodec().readTree(jp);
if(node.isNull() || node.asText().isEmpty()|| node.size()==0)
return null;
City city = new City();
... // set all fields
return city;
}
}
if 檢查條件:
'city' : null
'city' : ''
'city' : '{}'
如果為真,反序列化器返回null
。
做到這一點的唯一方法是使用自定義解串器:
class CustomDeserializer extends JsonDeserializer<String> {
@Override
public String deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException {
JsonNode node = jsonParser.readValueAsTree();
if (node.asText().isEmpty()) {
return null;
}
return node.toString();
}
}
然后做:
class EventBean {
public Long eventId;
public String title;
@JsonDeserialize(using = CustomDeserializer.class)
public String location;
}
這個解決方案由 Sach141 在這個問題上提供。
另一種方法是使用com.fasterxml.jackson.databind.util.Converter<IN,OUT>
,它本質上是用於反序列化的后處理器。
假設我們有一個 class:
public class Person {
public String id;
public String name;
}
現在假設我們想要將一個空的 JSON object {}
反序列化為null
,而不是將Person
的id
和name
值反序列化為null
。 我們可以創建以下Converter
:
public PersonConverter implements Converter<Person,Person> {
@Override
public Person convert(Person p) {
return isEmpty(p) ? null : value;
}
private static boolean isEmpty(Person p) {
if(p == null) {
return true;
}
if(Optional.ofNullable(p.id).orElse("").isEmpty() &&
Optional.ofNullable(p.name).orElse("").isEmpty()) {
return true;
}
return false;
}
@Override
public JavaType getInputType(TypeFactory typeFactory) {
return typeFactory.constructType(Person.class);
}
@Override
public JavaType getOutputType(TypeFactory typeFactory) {
return typeFactory.constructType(Person.class);
}
}
請注意,我們必須處理空白String
的情況,因為這是(違反直覺)分配給 JSON 中未給出的屬性的默認值,而不是null
。
給定轉換器,然后我們可以注釋我們原來的Person
class:
@JsonDeserialize(converter=PersonConverter.class)
public class Person {
public String id;
public String name;
}
這種方法的好處是您根本不必考慮或關心反序列化; 您只是在反序列化后決定如何處理反序列化的 object。 您還可以使用Converter
進行許多其他轉換。 但這對於使“空”值無效很有效。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.