将 Jackson ObjectMapper 与 Java 8 可选值一起使用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25693309/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using Hymanson ObjectMapper with Java 8 Optional values
提问by asieira
I was trying to use Hymanson to write a class value to JSON that has Optional as fields:
我试图使用 Hymanson 将一个类值写入具有 Optional 作为字段的 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()));
}
}
When executed, this class generates the following output:
执行时,此类生成以下输出:
{"field":{"present":true}}
I understand the present/not present field being included and could work around it when reading the JSON data, however I can't get around the fact that the actual content of the optional is never written to the output. :(
我了解包含的存在/不存在字段,并且在读取 JSON 数据时可以解决它,但是我无法解决可选的实际内容从未写入输出的事实。:(
Any workarounds here except not using ObjectMapper at all?
除了根本不使用 ObjectMapper 之外,还有其他解决方法吗?
采纳答案by Jonas
You could use Hymanson-datatype-jdk8which is described as:
您可以使用Hymanson-datatype-jdk8描述为:
Support for new JDK8-specific types, such as Optional
支持新的 JDK8 特定类型,例如 Optional
In order to do this:
为此:
- add
com.fasterxml.Hymanson.datatype:Hymanson-datatype-jdk8
as a dependency - register the module with your object mapper:
objectMapper.registerModule(new Jdk8Module());
- 添加
com.fasterxml.Hymanson.datatype:Hymanson-datatype-jdk8
为依赖项 - 使用您的对象映射器注册模块:
objectMapper.registerModule(new Jdk8Module());
回答by Manikandan
Define new getter which will return String instead of Optional.
定义新的 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);
}
}
回答by Sotirios Delimanolis
The Optional
class has a value
field, but no standard getter/setter for it. By default, Hymanson looks for getters/setters to find class properties.
该Optional
班有一个value
领域,但它没有标准的getter / setter。默认情况下,Hymanson 寻找 getter/setter 来查找类属性。
You can add a custom Mixin to identify the field as a property
您可以添加自定义 Mixin 以将该字段标识为属性
final class OptionalMixin {
private Mixin(){}
@JsonProperty
private Object value;
}
and register it with your ObjectMapper
.
并将其注册到您的ObjectMapper
.
ObjectMapper mapper = new ObjectMapper();
mapper.addMixInAnnotations(Optional.class, OptionalMixin.class);
You can now serialize your object.
您现在可以序列化您的对象。
System.out.println(mapper.writeValueAsString(new Test()));
will print
将打印
{"field":{"value":"hello, world!","present":true}}
Consider also looking at Hymanson-datatype-guava
. There's a Hymanson Module
implementation for Guava types including their Optional
. It's possibly more complete than what I've shown above.
考虑也看Hymanson-datatype-guava
。Module
Guava 类型有一个 Hymanson实现,包括它们的Optional
. 它可能比我上面显示的更完整。
回答by mjj1409
Similar to @Manikandan's answer but add @JsonProperty
to the private field instead of a getter so you don't expose your work around on the public api.
类似于@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);
}
}
回答by jiantongc
Try passing in options into @JsonInclude
annotation.
For example, if you don't want to show field
when the value is null
. You might need to use Hymanson-Modules >2.8.5.
尝试将选项传递到@JsonInclude
注释中。
例如,如果您不想显示field
值何时为null
。您可能需要使用 Hymanson-Modules >2.8.5。
import com.fasterxml.Hymanson.annotation.JsonInclude;
public class Test {
@JsonInclude(JsonInclude.Include.NON_NULL)
Optional<String> field;
}
回答by seenimurugan
If you are using latest version of Spring-boot then you could achieve this by adding the following dependency in the pom file
如果您使用的是最新版本的 Spring-boot,那么您可以通过在 pom 文件中添加以下依赖项来实现这一点
<dependency>
<groupId>com.fasterxml.Hymanson.datatype</groupId>
<artifactId>Hymanson-datatype-jdk8</artifactId>
</dependency>
And auto wire the HymansonObjectMapper.
并自动连接 HymansonObjectMapper。
@Autowired
private ObjectMapper HymansonObjectMapper;
Then use the above Spring container's mapper instance to convert Object to String
然后使用上面Spring容器的mapper实例将Object转为String
HymansonObjectMapper.writeValueAsString(user);
Some well known Hymanson modules are automatically registered if they are detected on the classpath:
- Hymanson-datatype-jdk7: Java 7 types like java.nio.file.Path (as of 4.2.1 release)
- Hymanson-datatype-joda: Joda-Time types
- Hymanson-datatype-jsr310: Java 8 Date & Time API data types
- Hymanson-datatype-jdk8: other Java 8 types like Optional (as of 4.2.0 release)
如果在类路径上检测到一些众所周知的 Hymanson 模块,则会自动注册:
- Hymanson-datatype-jdk7:Java 7 类型,如 java.nio.file.Path(从 4.2.1 版本开始)
- Hymanson-datatype-joda:Joda 时间类型
- Hymanson-datatype-jsr310:Java 8 日期和时间 API 数据类型
- Hymanson-datatype-jdk8:其他 Java 8 类型,如 Optional(从 4.2.0 版本开始)
回答by cakraww
You only need to register module Jdk8Module
. Then it will serialize any Optional<T>
as T
if it is present or null
otherwise.
您只需要注册 module Jdk8Module
。然后它将序列化任何内容Optional<T>
,就T
好像它存在或不存在一样null
。
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new Jdk8Module());
Let's modify Test
class a bit so we can test for an Optional.empty()
value. This is similar to the original Test
class when serialized because the object mapper is looking for the getter (since the field is private
). Using the original Test
class will work too, though.
让我们Test
稍微修改一下类,以便我们可以测试一个Optional.empty()
值。这与Test
序列化时的原始类相似,因为对象映射器正在寻找 getter(因为字段是private
)。不过,使用原始Test
类也可以。
class Test {
private final String field;
public Test(String field) {
this.field = field;
}
public Optional<String> getField() {
return Optional.ofNullable(field);
}
}
Then in our main class:
然后在我们的主类中:
Test testFieldNull = new Test(null);
Test testFieldNotNull = new Test("foo");
// output: {"field":null}
System.out.println(objectMapper.writeValueAsString(testFieldNull));
// output: {"field":"foo"}
System.out.println(objectMapper.writeValueAsString(testFieldNotNull));