幸运的是,有一个更简单的解决方案。
1)在ObjectMapper配置中,将序列化包含设置为仅包含不存在的字段:
@Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModules(vavr());
objectMapper.setSerializationInclusion(NON_ABSENT);
return objectMapper;
}
2)将可选字段的默认值设置为Option.none
:
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Foo {
private Option<String> bar = Option.none(); // If the JSON field is null or not present,the field will be initialized with none
}
就是这样!
更好的消息是它适用于所有Iterables,而不仅仅是Option。特别是它也适用于Vavr List
类型!
,
我找到了与不相容(lombok @Value)模型一起使用的解决方案:
- 使用未写入Option.None的mixIn在所有
Object
上添加过滤器(请参见下面的“解决方案”)
- 当缺少相应的json条目时,我现有的
ObjectMapper
(带有JavaslangModule
)已将“无”设置为“选项”字段
代码
import static org.assertj.core.api.Assertions.assertThat;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.PropertyWriter;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import javaslang.control.Option;
import javaslang.jackson.datatype.JavaslangModule;
import lombok.AllArgsConstructor;
import lombok.Value;
import org.junit.Test;
import java.io.IOException;
import java.lang.reflect.Field;
public class JsonModelAndSerialization {
// Write to Json
// =============
private static ObjectMapper objectMapper = new ObjectMapper()
.registerModule(new Jdk8Module())
.registerModule(new JavaslangModule())
// not required but provide forward compatibility on new field
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
static String write(Object data) throws JsonProcessingException {
SimpleBeanPropertyFilter filter = new NoneOptionPropertyFilter();
objectMapper.addMixIn(Object.class,NoneOptionFilter.class);
final SimpleFilterProvider filters = new SimpleFilterProvider().setDefaultFilter(filter);
ObjectWriter writer = objectMapper.writer(filters);
return writer.writeValueAsString(data);
}
// Filter classes
// ==============
@JsonFilter("Filter None")
private static class NoneOptionFilter {}
private static class NoneOptionPropertyFilter extends SimpleBeanPropertyFilter {
@Override
public void serializeAsField(
Object pojo,JsonGenerator jgen,SerializerProvider provider,PropertyWriter writer) throws Exception{
Field field = pojo.getClass().getDeclaredField(writer.getName());
if(field.getType().equals(Option.class)){
field.setAccessible(true);
Option<?> value = (Option<?>) field.get(pojo);
if(value.isEmpty()) return;
}
super.serializeAsField(pojo,jgen,provider,writer);
}
}
// Usage example
// =============
// **important note**
// For @Value deserialization,a lombok config file should be added
// in the source folder of the model class definition
// with content:
// lombok.anyConstructor.addConstructorProperties = true
@Value
@AllArgsConstructor(onConstructor_={@JsonCreator})
public static class StringInt {
private int intValue;
private Option<String> stringValue;
}
@Value
@AllArgsConstructor(onConstructor_={@JsonCreator})
public static class StringIntPair {
private StringInt item1;
private StringInt item2;
}
@Test
public void readWriteMyClass() throws IOException {
StringIntPair myClass = new StringIntPair(
new StringInt(6 * 9,Option.some("foo")),new StringInt( 42,Option.none()));
String json = write(myClass);
// {"item1":{"intValue":54,"stringValue":"foo"},"item2":{"intValue":42}}
StringIntPair myClass2 = objectMapper.readValue(json,StringIntPair.class);
assertThat(myClass2).isEqualTo(myClass);
}
}
优点:
- 使用
Option.None
时减小json的大小(因此,在模型中添加Option字段时不使用时不会消耗大小)
- 在以后在模型中添加选项类型的字段时,它提供向后读取兼容性(默认为
None
)
缺点:
- 无法区分无字段值的正确数据和错误地忘记了该字段的错误数据。我认为这是可以接受的。
本文链接:https://www.f2er.com/3059396.html