使用Jackson ObjectMapper和Java 8可选值
我试图使用jackson写一个类的值为JSON,可选的字段:
public class Test { Optional<String> field = Optional.of("hello, world!"); public Optional<String> getField() { return field; } public static void main(String[] args) throws JsonProcessingException { ObjectMapper mapper = new ObjectMapper(); System.out.println(mapper.writeValueAsString(new Test())); } }
执行时,这个类将生成以下输出:
{"field":{"present":true}}
我明白当前/不存在的领域被包括在内,并且可以在阅读JSON数据时解决它,但是我无法解决这个事实,即可选的实际内容从不写入输出。 🙁
任何解决方法在这里,除了根本不使用ObjectMapper?
你可以使用jackson-datatype-jdk8 ,描述如下:
支持新的特定于JDK8的types,例如可选
Optional
类有一个value
,但没有标准的getter / setter。 默认情况下,jackson寻找getter / setter来查找类属性。
您可以添加一个自定义Mixin以将该字段标识为属性
final class OptionalMixin { private Mixin(){} @JsonProperty private Object value; }
并注册它与您的ObjectMapper
。
ObjectMapper mapper = new ObjectMapper(); mapper.addMixInAnnotations(Optional.class, OptionalMixin.class);
你现在可以序列化你的对象。
System.out.println(mapper.writeValueAsString(new Test()));
将打印
{"field":{"value":"hello, world!","present":true}}
考虑一下jackson-datatype-guava
。 有一个jacksonModule
实施Guavatypes包括其Optional
。 这可能比我上面显示的更完整。
类似于@ Manikandan的答案,但添加@JsonProperty
到私人领域,而不是一个getter,所以你不暴露你的工作周围的公共api。
public class Test { @JsonProperty("field") private String field; @JsonIgnore public Optional<String> getField() { return Optional.of(field); // or Optional.ofNullable(field); } }
尝试将选项传入@JsonInclude
注释。
例如,如果您不想在值为null
时显示field
。 您可能需要使用Jackson-Modules> 2.8.5 。
import com.fasterxml.jackson.annotation.JsonInclude; public class Test { @JsonInclude(JsonInclude.Include.NON_NULL) Optional<String> field; }
定义新的getter将返回String而不是Optional。
public class Test { Optional<String> field = Optional.of("hello, world!"); @JsonIgnore public Optional<String> getField() { return field; } @JsonProperty("field") public String getFieldName() { return field.orElse(null); } }
如果您使用的是最新版本的Spring启动,那么您可以通过在pom文件中添加以下依赖项来实现此目的
<dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jdk8</artifactId> </dependency>
并自动连线JacksonObjectMapper。
@Autowired private ObjectMapper jacksonObjectMapper;
然后使用上面的Spring容器的映射器实例将Object转换为String
jacksonObjectMapper.writeValueAsString(user);
春季博客说:
如果在类path中检测到某些着名的Jackson模块,则会自动注册它们:
- jackson-datatype-jdk7:Java 7types,如java.nio.file.Path(从4.2.1版本开始)
- jackson-datatype-joda:Joda-Timetypes
- jackson-datatype-jsr310:Java 8date和时间API数据types
- jackson-datatype-jdk8:其他Java 8types,如可选(从4.2.0版本开始)