Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jackson throws JsonMappingException on deserialize; demands single-String constructor?

Tags:

java

json

jackson

Another question, but it relates to this one: Deserializing JSON with Jackson - Why JsonMappingException "No suitable constructor"?

This time I am getting a different error, namely that the Jackson deserializer complains that I do not have a "single-String constructor/factory method" in my class ProtocolContainer.

However, if I add a single-String constructor, like this:

public ProtocolContainer(String json) {}

the exception does indeed disappear, but the ProtocolContainer that I expected to be there is all "empty", i.e. all its properties are in their initial state, and not populated according to the JSON-string.

Why is that?

I'm pretty sure you shouldn't need a single-String constructor, and if you do that you should not have to populate the properties in that constructor, right?

=)

like image 431
Ted Avatar asked Dec 03 '11 16:12

Ted


2 Answers

Oh, so once again I found out the answer AFTER I posted this question (even though I tried a lot of things before posting).

What I did to solve this was to use the @JsonCreator annotation. I simply annotated my static Create method, like this:

@JsonCreator
public static ProtocolContainer Create(String jsonString)
{

    ProtocolContainer pc = null;
    try {
        pc = mapper.readValue(jsonString, ProtocolContainer.class);
    } catch (JsonParseException|JsonMappingException|IOException e) {
        // handle
    }

    return pc;
}

And then problem solved.

like image 124
Ted Avatar answered Oct 14 '22 09:10

Ted


The exception suggests that the JSON value you have is a String, something like:

{ "protocol" : "http" }

or perhaps "double-quoted JSON":

"\"{\"property\":\"value\"}\"

when trying to bind like:

ProtocolContainer p = mapper.readValue(json, ProtocolContainer.class);

in which case Jackson has no properties to map, just a String. And in that case it does indeed require either a custom deserializer, or a creator method. Creator methods are either single-string-argument constructors, or single-string argument static methods: the difference being that only constructors can be auto-detected (this is just a practical short-cut as there can only be one such constructor, but multiple static methods).

Your solution does indeed work, just thought I'd give some background as to what is happening.

Reading through it second time it seems more likely you have double-quoted stuff (JSON in JSON): another thing to consider is to get plain JSON, if possible. But maybe that's hard to do.

like image 31
StaxMan Avatar answered Oct 14 '22 09:10

StaxMan