【问题标题】:Jackson 2.11.4: Set Default Value For Missing JSON fieldJackson 2.11.4:为缺少的 JSON 字段设置默认值
【发布时间】:2021-09-02 16:43:57
【问题描述】:

我有以下 JSON

"Choices": [
        {
        "choiceId": "1"
        
    },
    {
        "choiceId": "2",
        "choiceType": null
    }
    ]

下面是 POJO,我需要两个构造函数,因为如果 json 中没有 choiceType 我需要将其默认为 Yes,如果 json 中的 choiceType 存在 null 值那么它应该不默认为Yes

@Getter
@ToString
@Setter
@NoArgsConstructor
public class Choices {
    @JsonProperty("choiceId")
    @NonNull
    private String choiceId;

    @JsonProperty("choiceType")
    private String choiceType;

    @JsonCreator
    @JsonIgnoreProperties(ignoreUnknown = true)
    public Choices(@JsonProperty("choiceId") String choiceId) {
        this.choiceType = choiceType !=null ? choiceType : "Yes";
        this.choiceId = choiceId;
    }

    public Choices(@JsonProperty("choiceId") String choiceId, @JsonProperty("choiceType") String choiceType) {
        this.choiceType = choiceType;
        this.choiceId = choiceId;
    }
}

我的目标是当上述 Json 被反序列化并且我有以下测试用例时,有一个选择列表

@Test
    public void testChoices(){
        ObjectMapper objectMapper = new ObjectMapper();
        String json = "[ { \"choiceId\": \"1\" }, { \"choiceId\": \"2\", \"choiceType\": null } ]";
        
        List<Choices> choices = objectMapper.convertValue(json, new TypeReference<List<Choices>>() {
        });
        assertTrue(choices.get(0).getChoiceId().equals("1"));
        assertTrue(choices.get(0).getChoiceType().equals("Yes"));
        assertTrue(choices.get(1).getChoiceType().equals("2"));
        assertNull(choices.get(1).getChoiceType());
    }

当我尝试反序列化下面的 json。我尝试了很多解决方案,但仍然没有运气,有人可以帮我解决这个问题吗?

Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Invalid definition for property `choiceType` (of type `com.onetrust.ds.request.dto.rest.Choices`): Could not find creator property with name 'choiceType' (known Creator properties: [choiceId])
 at [Source: UNKNOWN; line: -1, column: -1]

【问题讨论】:

  • 尝试不使用 Lombok。
  • @Nemanja 试过没有 Lombok 但没有运气

标签: java spring-boot java-8 jackson


【解决方案1】:

您可以摆脱 args 构造函数并将值默认为“是”。如果 value 显式设置为 null 或一个值,它将被分配。如果缺少值,它将被默认。

@Getter
@ToString
@Setter
@NoArgsConstructor
public class Choices {
    @JsonProperty("choiceId")
    @NonNull
    private String choiceId;

    @JsonProperty("choiceType")
    private String choiceType = "Yes";

}

参考 - Jackson: What happens if a property is missing?

【讨论】:

    【解决方案2】:

    看起来你的问题是你应该用@JsonCreator标记both构造函数。而且您只需要其中一个,Jackson 将默认将未设置的值填充为null(无需为此创建单独的构造函数)。

    import com.fasterxml.jackson.annotation.JsonCreator;
    import com.fasterxml.jackson.annotation.JsonProperty;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.ObjectReader;
    import lombok.Getter;
    
    public static void main(String[] args) throws IOException {
        String json = "[ { \"choiceId\": \"1\" }, { \"choiceId\": \"2\", \"choiceType\": null } ]";
        ObjectMapper mapper = new ObjectMapper();
        ObjectReader reader = mapper.readerFor(Choices.class);
        List<Choices> choices = reader.<Choices>readValues(json).readAll();
    }
    
    @Getter
    public static class Choices {
    
        private String choiceId;
        private String choiceType;
    
        @JsonCreator
        public Choices(@JsonProperty("choiceId") String choiceId,
                       @JsonProperty("choiceType") String choiceType) {
            this.choiceId = choiceId;
            this.choiceType = choiceType == null ? "Yes" : choiceType;
        }
    
    }
    

    我找到了这个例子here

    【讨论】:

    • 感谢您的回答。我需要两个构造函数,因为如果 json 中没有 choiceType 我需要将其默认为 Yes
    • 预期的行为是,如果 choiceTyoe 不存在于 json 中,那么我只需将值设置为 Yes 如果 choiceTyoe 存在且值为 null 那么它不应该设置为“是”。你可以仔细检查我的测试用例。使用您的代码,对于上述两种情况,我都将choiceTyoe 设为Yes
    猜你喜欢
    • 2013-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-29
    • 2020-06-27
    • 2019-05-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多