我需要根据条件序列化一些字段。
例如,我有以下课程。
public class ClassExample
{
private String id;
private String type;
private String string_1;
private String string_2;
}
因此,假设该类型可以接收两个值,"type_1"或"type_2",并且string_1和string_2将始终为null(它们将由另一个应用程序更改(。
我想使用Jackson来序列化它,我想:
1( 如果是type_1,字符串_1会显示在JSON中,字符串_2则不会。
2( 如果是类型_2,字符串_2会显示在JSON中,字符串_1则不会。
有办法做到这一点吗?
提前感谢
一个字段依赖于另一个字段的为空性可能是一个迹象,表明您应该将类拆分为2。您可以用两个类来代替一个包含两个可能值的类型字段,而不必在其中包含任何类型字段。因此不需要自定义序列化程序。
据我所知,您希望序列化符合条件的类字段。有多种方法可以解决这个问题,因为你想要的解决方案没有使用自定义序列化程序,这里有一个解决方案:-
该解决方案基于Jackson的FilterProvider。
建议:-
- 使用自定义序列化程序,如果您有非常严格的约束,请使用上面提到的解决方案
- 请将类型设为枚举,并根据相应的类型操作进行不同的实现
如果你能详细说明你的用例,我可以推荐一个更好的解决方案
解决方案:-
import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.ser.PropertyFilter;
import com.fasterxml.jackson.databind.ser.PropertyWriter;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
@Getter
@Setter
@Slf4j
@AllArgsConstructor
@JsonFilter("myFilter")
public class ClassExample {
private String id;
private String type;
private String string_1;
private String string_2;
private static final ObjectMapper om = new ObjectMapper();
private static final PropertyFilter theFilter = new SimpleBeanPropertyFilter() {
@Override
public void serializeAsField(Object pojo, JsonGenerator jgen,
SerializerProvider provider, PropertyWriter writer)
throws Exception {
if (include(writer)) {
if (!(writer.getName().equals("string_1") || writer.getName().equals("string_2"))) {
writer.serializeAsField(pojo, jgen, provider);
return;
}
String type = ((ClassExample) pojo).getType();
if ("type_1".equals(type) && (writer.getName().equals("string_1"))) {
writer.serializeAsField(pojo, jgen, provider);
} else if ("type_2".equals(type) && (writer.getName().equals("string_2"))) {
writer.serializeAsField(pojo, jgen, provider);
}
} else if (!jgen.canOmitFields()) { // since 2.3
writer.serializeAsOmittedField(pojo, jgen, provider);
}
}
@Override
protected boolean include(BeanPropertyWriter writer) {
return true;
}
@Override
protected boolean include(PropertyWriter writer) {
return true;
}
};
public String toString() {
try {
FilterProvider filters = new SimpleFilterProvider().addFilter("myFilter", theFilter);
return om.writer(filters).writeValueAsString(this);
} catch (Exception e) {
log.error("error while serialisation", e);
return "";
}
}
public static void main(String[] args) {
System.out.println(new ClassExample("123", "type_1", "1", "2"));
}
}
输出:
If type is type_1 then {"id":"123","type":"type_1","string_1":"1"}
If type if type_2 then {"id":"123","type":"type_2","string_2":"2"}