OTUser
OTUser

Reputation: 3848

Jackson 2.11.4: Set Default Value For Missing JSON field

I have the below JSON

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

below is the POJO and I need to have both the constructors because if there is no choiceType in json I need to default it to Yes, if choiceType in json exists with null value then it should not default to 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;
    }
}

And my goal is to have a list of choices when the above Json is deserialized and I have below test case

@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());
    }

When I try to deserialize the below json. I have tried many solutions but still no luck, can someone please help me witht this?

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]

Upvotes: 5

Views: 10561

Answers (2)

s7vr
s7vr

Reputation: 75944

You could just get rid of the args constructor and default the value to "Yes". If value is explicitly set to null or to a value it will be assigned. In case of missing value it will be defaulted.

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

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

}

Reference - Jackson: What happens if a property is missing?

Upvotes: 8

Oleg Cherednik
Oleg Cherednik

Reputation: 18245

Looks like your problem is you should mark both constructors with @JsonCreator. And you need only one of them, Jackson will fill not set values to null by default (no need to create separate constructor for that).

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;
    }

}

I have found this example here

Upvotes: 0

Related Questions