serialization - Jackson-Serializer:在序列化时忽略字段
问题描述
我的情况需要更复杂的序列化。我有一堂课Available
(这是一个非常简化的片段):
public class Available<T> {
private T value;
private boolean available;
...
}
所以一个 POJO
class Tmp {
private Available<Integer> myInt = Available.of(123);
private Available<Integer> otherInt = Available.clean();
...
}
通常会导致
{"myInt":{available:true,value:123},"otherInt":{available:false,value:null}}
但是,我想要一个序列化程序来呈现相同的 POJO,如下所示:
{"myInt":123}
我现在拥有的:
public class AvailableSerializer extends JsonSerializer<Available<?>> {
@Override
public void serialize(Available<?> available, JsonGenerator jsonGenerator, SerializerProvider provider) throws IOException, JsonProcessingException {
if (available != null && available.isAvailable()) {
jsonGenerator.writeObject(available.getValue());
}
// MISSING: nothing at all should be rendered here for the field
}
@Override
public Class<Available<?>> handledType() {
@SuppressWarnings({ "unchecked", "rawtypes" })
Class<Available<?>> clazz = (Class) Available.class;
return clazz;
}
}
一个测试
@Test
public void testSerialize() throws Exception {
SimpleModule module = new SimpleModule().addSerializer(new AvailableSerializer());
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(module);
System.out.println(objectMapper.writeValueAsString(new Tmp()));
}
输出
{"myInt":123,"otherInt"}
谁能告诉我如何做“失踪”的东西?或者如果我做错了,那我该怎么做?
我的限制是我不希望开发人员一直将@Json...
-annotations 添加到 type 的字段中Available
。所以Tmp
上面的 -class 是一个典型的 using 类应该是什么样子的例子。如果可以的话...
解决方案
包括.NON_DEFAULT
如果我们假设你的clean
方法是这样实现的:
class Available<T> {
public static final Available<Object> EMPTY = clean();
//....
@SuppressWarnings("unchecked")
static <T> Available<T> clean() {
return (Available<T>) EMPTY;
}
}
您可以将序列化包含设置为JsonInclude.Include.NON_DEFAULT
值,它应该跳过设置为EMPTY
(默认)值的值。请参见下面的示例:
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import java.io.IOException;
public class JsonApp {
public static void main(String[] args) throws Exception {
SimpleModule module = new SimpleModule();
module.addSerializer(new AvailableSerializer());
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(module);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT);
System.out.println(objectMapper.writeValueAsString(new Tmp()));
}
}
class AvailableSerializer extends JsonSerializer<Available<?>> {
@Override
public void serialize(Available<?> value, JsonGenerator jsonGenerator, SerializerProvider provider) throws IOException {
jsonGenerator.writeObject(value.getValue());
}
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
public Class<Available<?>> handledType() {
return (Class) Available.class;
}
}
上面的代码打印:
{"myInt":123}
自定义 BeanPropertyWriter
如果您不想使用Include.NON_DEFAULT
,您可以编写自定义BeanPropertyWriter
并跳过您想要的所有值。请参见下面的示例:
import com.fasterxml.jackson.core.JsonGenerator;
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.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class JsonApp {
public static void main(String[] args) throws Exception {
SimpleModule module = new SimpleModule();
module.addSerializer(new AvailableSerializer());
module.setSerializerModifier(new BeanSerializerModifier() {
@Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
List<BeanPropertyWriter> writers = new ArrayList<>(beanProperties.size());
for (BeanPropertyWriter writer : beanProperties) {
if (writer.getType().getRawClass() == Available.class) {
writer = new SkipNotAvailableBeanPropertyWriter(writer);
}
writers.add(writer);
}
return writers;
}
});
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(module);
System.out.println(objectMapper.writeValueAsString(new Tmp()));
}
}
class AvailableSerializer extends JsonSerializer<Available<?>> {
@Override
public void serialize(Available<?> value, JsonGenerator jsonGenerator, SerializerProvider provider) throws IOException {
jsonGenerator.writeObject(value.getValue());
}
@Override
@SuppressWarnings({"unchecked", "rawtypes"})
public Class<Available<?>> handledType() {
return (Class) Available.class;
}
}
class SkipNotAvailableBeanPropertyWriter extends BeanPropertyWriter {
SkipNotAvailableBeanPropertyWriter(BeanPropertyWriter base) {
super(base);
}
@Override
public void serializeAsField(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception {
// copier from super.serializeAsField(bean, gen, prov);
final Object value = (_accessorMethod == null) ? _field.get(bean) : _accessorMethod.invoke(bean, (Object[]) null);
if (value == null || value instanceof Available && !((Available) value).isAvailable()) {
return;
}
super.serializeAsField(bean, gen, prov);
}
}
上面的代码打印:
{"myInt":123}
推荐阅读
- c++ - reinterpret_cast 使 constexpr 函数失败
- r - 如果代码花费太长时间,则补救措施,从不给出结果
- reactjs - 有没有办法使用模板文字来获取请求?
- paypal-subscriptions - 使用 cmd=_xclick-subscriptions 的 Paypal 定期付款不返回交易数据以返回 url
- angular - 如何在Angular中我自己的DataTable中实现过滤?
- angular - 将数组推送到数据源时不绘制剑道角度图
- java - Apache POI 不在 xls 中写入一些值 - Java
- node.js - 在我的 Windows 主机文件中添加 LB IP 后,无法连接在浏览器上使用 ingress-nginx 生成的 Google Cloud Load Balancer
- html - 将 z-index 应用于图像
- r - 文件中的错误(描述 = xlsxFile):无效的“描述”参数