2

I am retrieving data from an API endpoint that returns data in two different expected json formats. One of the responses is a success response and one of the responses is a failure response. The other endpoints in the API are similar and also have a success and failure format. For most of the endpoints I just deserialize both types of responses into a single Java object where some fields are just set to default/null values when not present. My problem with this endpoint is that the success response is a json array and the fail response is a json object. I have tried everything to have a simple way to deserialize both of these possible responses into a single java object.

Example success json.

[
    {
        "item1": "somevalue1",
        "item2": "somevalue2"
    },
    {
        "item1": "somevalue3",
        "item2": "somevalue4"
    },
    ..
    ..
]

Example fail json

{
    "success": false,
    "errorMessage": "something went wrong "
}

My Java class I am currently using works to deserialize the success json but not for the fail json.

public class ResponseObject {
    public final boolean success;
    public final String errorMessage;
    public final List<MyItem> items;

    @JsonCreator
    public ResponseObject(ArrayList<MyItem> items) {
       this.items = items;
    }

}

And I also have a constructor that works for the fail case but not for the success case

public class ResponseObject {
    public final boolean success;
    public final String errorMessage;
    public final List<MyItem> items;

    @JsonCreator
    public ResponseObject(@JsonProperty("success") Boolean success, @JsonProperty("errorMessage") String errorMessage){
        this.success = success == null;
        this.errorMessage = errorMessage;
        this.items = items;
    }

}

My deserialization code looks something like

ObjectReader objectReader = objectMapper.readerFor(ResponseObject.class);
Object json = objectReader.readValue(inputStream);

Whatever strategy I have tried to be able to deserialize both cases generically seems to fail. If I try to include the json array in the constructor with a @JsonProperty then I have no name/value to refer to the array of items, and the code throws an exception.

What I need is a way to deserialize both responses into the ResponseObject format that I outlined, when I get the success reponse the success field should be true, the errorMessage should be null and the items should contain a list of MyItem. When I get a fail response, the success should be false, the errorMessage should have a string message and the items list should be null.

How can I achieve this? Or, how else can I structure my code to handle multiple expected json formats? I know I could deserialize to a TreeMap, check the format and then convert again to the final object for example, but I would like to skip this intermediate step.

Thanks for any advice that anyone can give me on this one :)

0

2 Answers 2

2

You can try to make a superclass

public class ResponseObject {

    public final boolean success;
    public final String errorMessage;
    public final List<MyItem> items;

    ...
}

and then organize the fail and success messages in a

public class SuccesResponseObject extends ResponseObject {...}

and

public class FailResponseObject extends ResponseObject {...}

with the corresponding constructors. The properties will be situated in the superclass. When using the classes, you should refer to them of being of the class ResponseObject.

Sign up to request clarification or add additional context in comments.

Comments

0

If you add a POJO for the error message, you could add a second JsonCreator to your Response Object.

public class ErrorResponse {
    private boolean success;
    private String errorMessage;
    public boolean isSuccess() {
        return success;
    }
    public void setSuccess(boolean success) {
        this.success = success;
    }
    public String getErrorMessage() {
        return errorMessage;
    }
    public void setErrorMessage(String errorMessage) {
        this.errorMessage = errorMessage;
    }
}

Modified ResponseObject with 2 JsonCreator

public class ResponseObject {
    public final boolean success;
    public final String errorMessage;
    public final List<MyItem> items;

    @JsonCreator
    public ResponseObject(List<MyItem> items) {
       this.success = true;
       this.errorMessage = null;
       this.items = items;
    }

    @JsonCreator
    public ResponseObject(ErrorResponse error){
        this.success = error.isSuccess();
        this.errorMessage = error.getErrorMessage();
        this.items = null;
    }

}

1 Comment

This absolutely solved my problem and original question. :) it works.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.