David Alvarez
David Alvarez

Reputation: 1286

@JsonIgnoreProperties(ignoreUnknown = true) does not have expected behaviour

I'm working on a feature on which I get an address from outside, and need to parse it into a Java class:

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class AddressDTO {
    @JsonProperty(value = "Name")
    private String name;
    @JsonProperty("Street")
    private String street;
    @JsonProperty("City")
    private String city;
    @JsonProperty("PostalCode")
    private String postalCode;
    @JsonProperty("CountryISO")
    private String countryIso;
    @JsonProperty("Region")
    private String region;
}

and this os how I convert it:

        try {
            final var type = new TypeReference<AddressDTO>() {
            };
            final var address = (AddressDTO) new ObjectMapper()
                    .readerFor(type)
                    .readValue(jsonAddress);

            return mapper.toAddress(address);
        } catch (final Exception e) {
            LOG.error("unable to parse the variable 'address'", e);
            throw new BadFormatException();
        }

I want only those fields, but it may happend that sometimes the payload from outside also contains "Street2", "Name2" or other fields. When this happens, this exception is thrown: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "Street2".

After having search how to solve this, I came accross the property @JsonIgnoreProperties(ignoreUnknown = true), which is supposed to ignore unknown fields:

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true) // Some old value might contain additional old fields 😥
public class AddressDTO {
    @JsonProperty(value = "Name")
    private String name;
    @JsonProperty("Street")
    private String street;
    @JsonProperty("City")
    private String city;
    @JsonProperty("PostalCode")
    private String postalCode;
    @JsonProperty("CountryISO")
    private String countryIso;
    @JsonProperty("Region")
    private String region;
}

When I put that annotation, I stopped having the exception above, but I encountered a new problem: all the other fields where ignored:

{
  "NonExistingKey1": "foo",
  "Non_existing_key2": "bar"
}

was transformed like that: enter image description here.

How can I annotate my class so that it does not throw an exception when there are more fields than expected, but still checks if all the properties are present and not null ?

Upvotes: 1

Views: 5061

Answers (1)

Alex
Alex

Reputation: 866

First you can use constructor-based property assignment like

@Data
@Builder
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true) // Some old value might contain additional old fields 😥
public class AddressDTO {
    private String name;
    private String street;
    private String city;
    private String postalCode;
    private String countryIso;
    private String region;

    public AddressDTO(@JsonProperty(value = "Name") String name,
                      @JsonProperty(value = "Street") String street,
                      @JsonProperty("City") String city,
                      @JsonProperty("PostalCode") String postalCode,
                      @JsonProperty("CountryISO") String countryIso,
                      @JsonProperty("Region") String region) {
        this.name = name;
        this.street = street;
        this.city = city;
        this.postalCode = postalCode;
        this.countryIso = countryIso;
        this.region = region;
    }
}

Then you can configure ObjectMapper to fail on missing properties:

objectMapper.configure(DeserializationFeature.FAIL_ON_MISSING_CREATOR_PROPERTIES, true);

Upvotes: 1

Related Questions