2

with Jackson, I'm trying to properly deserialize a JSON which contains empty string as no value values. Herein an example:

{
  "code" : "REQ500",
  "description" : "Problem with Service",
  "params" : ""
}

and the bean I would get:

public final class MyError {

    @JsonProperty("code")
    private String code;

    @JsonProperty("description")
    private String description;

    @JsonProperty("params")
    private List<String> params;

    // [CUT]

    public void setParams(List<String> params) {
        this.params = params;
    }
}

Using ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, I've create an object mapper with

public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper()
    .configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true)
    .registerModule(new SimpleModule().addDeserializer(LocalDate.class, new DateDeserializer()));

expecting to have params = null, but deserialization doesn't work. Herein the error I got:

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot 
deserialize instance of `java.util.ArrayList` out of VALUE_STRING token
 at [Source: (String)"{
  "code" : "REQ500",
  "description" : "Problem with Service",
  "params" : ""
}"; line: 4, column: 14] (through reference chain: solutions.infinitec.fabrick.models.common.MyError["params"])

    at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)

Any hints on how to solve this issue? Am I wrong somewhere?

Thank you in advance for suggestions.

Gilberto T.
  • 358
  • 6
  • 19

3 Answers3

1

I tried it using ACCEPT_SINGLE_VALUE_AS_ARRAY and it works as expected.

ObjectMapper om = new ObjectMapper();
om.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);

MyJson asString = om.readValue("{\n"
            + "  \"code\" : \"REQ500\",\n"
            + "  \"description\" : \"Problem with Service\",\n"
            + "  \"params\" : \"\"\n"
            + "}", MyError.class);

MyJson asArray = om.readValue("{\n"
            + "  \"code\" : \"REQ500\",\n"
            + "  \"description\" : \"Problem with Service\",\n"
            + "  \"params\" : [\"\"]\n"
            + "}", MyError.class);

The only thing you have to handle is the response containing just a single element in params which is empty.

Another way could be this definition of MyError:

public class MyError {

    @JsonProperty("code")
    private String code;

    @JsonProperty("description")
    private String description;

    private List<String> params;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public List<String> getParams() {
        return params;
    }

    @JsonProperty("params")
    private void setParams(JsonNode params) {
        if (params.isArray()) {
            this.params = new ArrayList<>();
            for(JsonNode child : params) {
                this.params.add(child.asText());
            }
        }
    }
}
Halko Karr-Sajtarevic
  • 2,248
  • 1
  • 16
  • 14
0

Just implement a setter method which accept string:

public void setParams(String params) {
    this.params = null;
}

if want to accept array:

public void setParams(String[] params) {
    this.params = Arrays.asList(params);
}
GolamMazid Sajib
  • 8,698
  • 6
  • 21
  • 39
0

I'd try using

OBJECT_MAPPER.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);

As shown in "Cannot deserialize instance of java.util.ArrayList"

Worthless
  • 531
  • 3
  • 7
  • Thanks for your answer. Can you please explain how this API solves the problem. – Elletlar Jul 23 '18 at 09:46
  • 1
    Already tried, it doesn't solve my issue given that, unfortunately, `ObjectMapper::enable` has the same behaviour of configuring `ACCEPT_SINGLE_VALUE_AS_ARRAY ` equal to `true`. – Gilberto T. Jul 23 '18 at 09:51