Search code examples
javajsonspring-bootjacksonjson-deserialization

@JsonView does not filter fields


I have problem while deserializing JSON to Java Object. I have models and views as shown below:

public class View {
    public static class CreateIpSuccessResponse {}
    public static class CreateIpErrorResponse {}
}

I use this views in this classes:

Root class:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class CreateIpResponse {
    @JsonProperty(value = "pResponseCode")
    @JsonView({View.CreateIpSuccessResponse.class, View.CreateIpErrorResponse.class})
    private Object pResponseCode;
    @JsonProperty(value = "pResponse")
    @JsonView({View.CreateIpSuccessResponse.class, View.CreateIpErrorResponse.class})
    private CreateIpPResponse createIpPResponse;
}

First subclass:

@Data
public class CreateIpPResponse {
    @JsonProperty("Status")
    @JsonView({View.CreateIpSuccessResponse.class, View.CreateIpErrorResponse.class})
    private String status;
    @JsonProperty("Result")
    @JsonView({View.CreateIpSuccessResponse.class, View.CreateIpErrorResponse.class})
    private CreateIpResult result;
    @JsonProperty("responseCode")
    @JsonView({View.CreateIpSuccessResponse.class, View.CreateIpErrorResponse.class})
    private String responseCode;
}

Second subclass:

@Data
public class CreateIpResult {
    @JsonProperty(value = "partyid")
    @JsonView(View.CreateIpSuccessResponse.class)
    private String partyId;

    @JsonProperty(value = "Error")
    @JsonView(View.CreateIpErrorResponse.class)
    private String error;
}

Example of my json deserialization:

    public CreateIpResponse createIp(CreateIpRequest createIpRequest) throws IOException, SQLException {
        String pRequest = new ObjectMapper().writer().withDefaultPrettyPrinter().writeValueAsString(createIpRequest);
        Map<String, Object> response = openAccountRepository.callProcedure(pRequest, "createClientIP");
        BigDecimal responseCode = (BigDecimal) response.get("pResponseCode");
        if (responseCode.equals(new BigDecimal("200"))) {
            return mapper
                    .readerWithView(View.CreateIpSuccessResponse.class)
                    .forType(CreateIpResponse.class)
                    .readValue(mapper.writeValueAsString(response));
        } else {
            return mapper
                    .readerWithView(View.CreateIpErrorResponse.class)
                    .forType(CreateIpResponse.class)
                    .readValue(mapper.writeValueAsString(response));
        }
    }

When I deserialize CreateIpSuccessResponse view, I expect:

{
    "pResponseCode": 200,
    "pResponse": {
        "Status": "OK",
        "Result": {
            "partyid": "98493305"
        },
        "responseCode": "200"
    }
}

But I get:

{
    "pResponseCode": 200,
    "pResponse": {
        "Status": "OK",
        "Result": {
            "partyid": "98493305",
            "Error": null
        },
        "responseCode": "200"
    }
}

and vice versa, when I deserialize CreateIpErrorResponse view, I expect:

{
    "pResponseCode": 400,
    "pResponse": {
        "Status": "Error",
        "Result": {
            "Error": "Некорректная дата выпуска"
        },
        "responseCode": "200"
    }
}

But I get:

{
    "pResponseCode": 400,
    "pResponse": {
        "Status": "Error",
        "Result": {
            "partyid": null,
            "Error": "Некорректная дата выпуска"
        },
        "responseCode": "200"
    }
}

My question is why i don`t getting result that i need?


Solution

  • It seems that ObjectMapper is not ignoring null values when serializing objects. So when creating he object mapper use the setSerializationInclusion(Include.NON_NULL) method call to tell the ObjectMapper to ignore the null values:

    ObjectMapper mapper = new ObjectMapper();
    mapper.setSerializationInclusion(Include.NON_NULL);
    

    You can find the details here

    Edit: added the summarization of the solution as moken suggested in comments.