8

I am using Jackson 2 library and I am trying to read a JSON response, which looks like:

{ "value":"Hello" }

When value is empty, JSON response looks like:

{ "value":{} }

My model POJO class looks like this

public class Hello {

    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

}

The problem is that when response looks like {value:{}}, Jackson is trying to read an Object, but my model class field is a string, so it throws an Exception:

JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token. 

My question is how Jackson can successfully read JSONs who look like:

 {"value":"something"} 

and at the same time if response looks like this {"value":{}} (empty response for me), pass null to value field of my Hello model class.

I am using the code below in order to read JSON string:

String myJsonAsString = "{...}";
ObjectMapper mapper = new ObjectMapper();
mapper.readValue(myJsonAsString , Hello.class);
4
  • Isn't there any way to fix the part that generates this JSON, instead of working around ths ugly design? Commented Mar 11, 2017 at 20:08
  • Nope there isn't unfortunately. API is not mine. I am just the client side. Commented Mar 11, 2017 at 20:12
  • Ouch, proper output would leave out the field or set it to null... Commented Mar 11, 2017 at 20:24
  • It's not that odd. MongoDB queries often have parts of the JSON that can be strings or objects. Commented Jul 30, 2022 at 0:57

2 Answers 2

15

You can use a custom deserializer for this feld. Here is one that returns the string if it's there, or null in any other case:

public class Hello {

    @JsonDeserialize(using = StupidValueDeserializer.class)
    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

public class StupidValueDeserializer extends JsonDeserializer<String> {
    @Override
    public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        JsonToken jsonToken = p.getCurrentToken();
        if (jsonToken == JsonToken.VALUE_STRING) {
            return p.getValueAsString();
        }
        return null;
    }
}
Sign up to request clarification or add additional context in comments.

Comments

2

Txh for JB Nizet, but if you get type another than String (e.g Object), Jackson deserialiser tried to deserialize inner Object and can throw a latent exception. After that, other fields in json filled as null in Java.

To avoid this you'll ignore children

@Override
public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
    JsonToken jsonToken = p.currentToken();
    if (jsonToken == JsonToken.VALUE_STRING) {
        return p.getValueAsString();
    }
    p.skipChildren();
    return "other_string";
}

Comments

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.