英文:
Deserialization null value to enum with Jackson
问题
我在JSON反序列化和映射到枚举方面遇到问题。我从外部API获取JSON,类似于以下两个示例:
{
"someValue": null
}
{
"someValue": "exists"
}
我想将空值映射到某个默认的枚举值。
模型对象:
SomeEnum someValue;
以及枚举类:
public enum SomeEnum {
@JsonProperty("exists") EXISTS,
NONE;
}
对于 "exists" 值,模型类中包含了正确的枚举值,但如果我从API获取到 null
,在模型中仍然是 null
。
我尝试过创建一些被 @JsonCreator
注解标记的方法,创建自己的枚举反序列化器,使用 @JsonEnumDefaultValue
,但这些解决方案都不适用于我。有人知道如何将 null 反序列化为某个默认的枚举值吗?
英文:
I have problem with JSON deserialization and mapping it to enum. I'm getting JSON from external API simillar to this two examples:
{
"someValue": null
}
{
"someValue": "exists"
}
I would like to map null values to some default enum value.
Model object
SomeEnum someValue;
and enum class
public enum SomeEnum {
@JsonProperty("exists") EXISTS,
NONE;
}
For exists, value model class contains correct enum, but if I get null
from API, it is still null
in the model.
I tried to create some method annotated by @JsonCreator
, creating own enum deserializer, using @JsonEnumDefaultValue
but none of these solutions work for me. Do anyone knows, how can I deserialize nulls to some default enum?
答案1
得分: 0
(老实说,我在这里编写了这段代码,但没有测试过,也许你需要稍微修改一下)
你可以尝试像下面这样做(使用带有构造函数和使用 @JsonCreator
的 Enum
):
public enum SomeEnum {
EXISTS("exists"),
NONE(null);
private String value;
SomeEnum(String value) {
this.value = value;
}
@JsonCreator
public static SomeEnum fromValue(String value) {
for (SomeEnum someEnum : SomeEnum.values()) {
if (StringUtils.equalsIgnoreCase(someEnum.getValue(), value)) {
return someEnum;
}
}
throw new IllegalArgumentException("Unknown value " + value);
}
public String getValue() {
return value;
}
}
如果不起作用,保留上面的枚举,并尝试创建一个自定义转换器(不使用 Jackson),如下所示:
如果使用 Spring Boot,你应该将这个绑定器放在你的控制器中:
@InitBinder
public void initBinder(final WebDataBinder webdataBinder) {
webdataBinder.registerCustomEditor(SomeEnum.class, new SomeEnumConverter());
}
以下是自定义转换器,用于指定如何将输入值转换为枚举值:
public class SomeEnumConverter extends PropertyEditorSupport {
@Override
public void setAsText(final String text) {
setValue(SomeEnum.fromValue(text));
}
}
英文:
(Honestly, I wrote this code here without testing it, maybe you need to modify it a bit)
You can try to do something like following (Enum
with a constructor and use @JsonCreator
):
public enum SomeEnum {
EXISTS("exists"),
NONE(null);
private String value;
SomeEnum (String value) {
this.value = value;
}
@JsonCreator
public static SomeEnum fromValue(String value) {
for (SomeEnum someEnum : SomeEnum.values()) {
if (StringUtils.equalsIgnoreCase(someEnum.getValue(), value)) {
return someEnum;
}
}
throw new IllegalArgumentException("Unknown value " + value);
}
public String getValue () {
return value;
}
}
If it doesn't work, keep the above enum and try to make a custom converter (without Jackson) as following
If using spring boot You should put this binder in your controller
@InitBinder
public void initBinder(final WebDataBinder webdataBinder) {
webdataBinder.registerCustomEditor(SomeEnum.class, new SomeEnumConverter());
}
The following is the custom converter to specify how you convert your input value to an enum value.
public class SomeEnumConverter extends PropertyEditorSupport {
@Override
public void setAsText(final String text) {
setValue(SomeEnum.fromValue(text));
}
}
答案2
得分: 0
好的,目前我通过创建自定义的枚举反序列化器来解决了这个问题。
class SomeEnumDeserializer extends StdDeserializer<SomeEnum> {
SomeEnumDeserializer() {
super(SomeEnum.class);
}
@Override
public SomeEnum getNullValue(DeserializationContext ctxt) {
return SomeEnum.NONE;
}
@Override
public SomeEnum deserialize(JsonParser p, DeserializationContext ctxt) {
// 在这里实现逻辑
}
}
然后使用 @JsonDeserialize 进行注册:
@JsonDeserialize(using = SomeEnumDeserializer.class)
public enum SomeEnum {
// 代码部分
}
但我仍然希望能够使用类似 @JsonProperty 的方式来处理 null 值,比如 @JsonNullProperty 或类似的方法。
英文:
Ok, so for now I solved this issue by creating custom enum deserializer.
class SomeEnumDeserializer extends StdDeserializer<SomeEnum> {
SomeEnumDeserializer() {
super(SomeEnum.class);
}
@Override
public SomeEnum getNullValue(DeserializationContext ctxt) {
return SomeEnum.NONE;
}
@Override
public SomeEnum deserialize(JsonParser p, DeserializationContext ctxt) {
// implementation here
}
and registering it using @JsonDeserialize:
@JsonDeserialize(using = SomeEnumDeserializer.class)
public enum SomeEnum {
// code
}
But still I'd prefer using something like @JsonProperty but for null, like @JsonNullProperty or something like this.
答案3
得分: 0
设置字段的初始值为枚举值。
public class ExampleClass {
@JsonProperty("someValue") public SomeEnum someValue = SomeEnum.NONE;
public enum SomeEnum {
@JsonProperty("exists") EXISTS,
NONE;
}
}
然而,这意味着如果该值不存在,它也将与指定null
时的值相同。因此,以下两个 JSON 字符串将生成相同的 POJO:
{}
{"someValue":null}
不确定您是否希望出现这种行为。
英文:
Set the starting value of the field to the enum's value.
public class ExampleClass {
@JsonProperty("someValue") public SomeEnum someValue = SomeEnum.NONE;
public enum SomeEnum {
@JsonProperty("exists") EXISTS,
NONE;
}
}
However, this will mean if the value doesn't exist it will also be the same value as if null
was specified. So these two JSON strings will produce the same POJO:
{}
{"someValue":null}
Not sure if that behavior is desired by you.
专注分享java语言的经验与见解,让所有开发者获益!
评论