使用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版本开始)