【问题标题】:How do you specify default values for Jackson deserialization如何为 Jackson 反序列化指定默认值
【发布时间】:2019-01-23 11:06:02
【问题描述】:
@ResponseBody
@RequestMapping(value="/getUser")
public JSONObject getContent(@ReqeustBody User user) 

这里是我的控制器代码。

@Data
public class User{
    private String username = "administrator";
    private String password = "123456";   
    private Integer age = 18;
}

这里是我的User 课程代码。

{
    "username":"admin",
    "password":"000",
    "age":""
}

当我POST 上面的JSON 时,我得到age 属性为null

我希望 Jackson 使用默认值反序列化 JSON 中的空字段(""null)。

像这样:

{
    "username":"admin",
    "password":"000",
    "age":18
}

我该怎么办?

【问题讨论】:

  • here
  • 奇怪的是,年龄字段已初始化,但据我所知,它在响应中丢失了

标签: java spring-boot jackson


【解决方案1】:

您可以定义一个自定义 getter 属性,在 null 的情况下设置默认值。

   public Integer getAge() {
        if (age == null) {
            return 18;
        } else {
            return this.age;
        }
    }

请注意,您无法更改 setAge 方法,因为在这种情况下不会调用它,事实上没有 age 字段会通知 Jackson 调用该方法。


另一种方法是使用自定义构造函数并使用带有值Nulls.SKIPJsonSetter 注释

表示应跳过输入空值且不进行赋值的值; 这通常意味着该属性将具有其默认值

如下:

 public class User {
    @JsonSetter(nulls = Nulls.SKIP)
    private Integer age;

    public User() {
        this.age = 18;
    }

    ...
}

@JsonSetter 存在于包 com.fasterxml.jackson.annotation 中,可以使用 maven 作为依赖项导入

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>YOURVERSION</version>
</dependency>

【讨论】:

  • 我没有找到可以在字段上写的JsonSetter 注释,com.fasterxml.jackson.annotation.JsonSetter 只允许在classmethod 上。
  • @Michael 它存在于 com.fasterxml.jackson.annotation 包中。查看更新的答案了解详情
  • 谢谢Davide,我的版本是2.8.0,不能写在field上。
  • @Michael 正确,因为源代码中的注释建议// ^^^ allowed on Fields, (constructor) parameters since 2.9
【解决方案2】:

一种方法是让你setAge处理null的情况,例如:

 void setAge(Integer age){
   if(age!=null) this.age = age;
 }

或者你可以看看@JsonSetter(nulls=Nulls.SKIP),我只是看了源码,没试过:(

希望对您有所帮助。

【讨论】:

  • setAge 不起作用,因为没有年龄字段。如果有一个年龄字段为空值,它可以工作,但在没有年龄字段的情况下就不行。
  • @DavideLorenzoMARINO 啊,我刚刚看到 lombok 的 @Data 注释(我假设),所以那里没有二传手。这实际上有点棘手,但它的 java 的本质,即使没有设置器,客户端代码仍然可以通过使用反射来更改对象的字段值,我假设杰克逊就是这样做的。我认为您的回答在您仍想使用 @Data 的情况下是有道理的。
【解决方案3】:

使用带有值 [Nulls.SKIP][2] 的 [JsonSetter][1] 注释

表示应跳过输入空值并进行默认分配的值; 这通常意味着该属性将具有其默认值

如下:

 public class User {
    @JsonSetter(nulls = Nulls.SKIP)
    private Integer Score = 1000;
    ...
}

通常,如果您不使用@JsonSetter(nulls = Nulls.SKIP),那么如果 JSON 中没有值,则默认值将被初始化,但如果有人明确输入 null,则可能会导致问题。使用@JsonSetter(nulls = Nulls.SKIP) 将告诉Json de-searilizer 避免null 初始化


[1]:https://fasterxml.github.io/jackson-annotations/javadoc/2.0.0/com/fasterxml/jackson/annotation/JsonSetter.html [2]:https://fasterxml.github.io/jackson-annotations/javadoc/2.9/com/fasterxml/jackson/annotation/Nulls.html#SKIP

【讨论】:

    猜你喜欢
    • 2018-07-15
    • 2017-01-31
    • 2019-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-07
    相关资源
    最近更新 更多