0

I am trying to deserialise a JSON-RPC object with Jackson. The format of JSON-RPC is :

{ "result": "something", "error": null, "id": 1}

In my case the result property is an generic Object.

I have a class for deserilising the response:

public class JsonRpcResponse {

private Object result;
private JsonRpcError error;
private int id;

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public JsonRpcError getError() {
    return error;
}

public void setError(JsonRpcError error) {
    this.error = error;
}

public Object getResult() {
    return result;
}

public void setResult(Object result) {
    this.result = result;
}

}

I can get the response object with:

 JsonRpcResponse jsonResp = mapper.readValue(response, JsonRpcResponse.class);

I want to have a generic method that deserializes this result object by passing to the method the type of the object (or the class if you want) that is going to be deserialized to. This way I can pass any type of object depending of the response I expect.

For example, I have this class with two properties:

public class JsonEventProperties {

private String conditon;
private String usage;

public JsonEventProperties(String condition, String usage) {
    this.conditon = condition;
    this.usage = usage;
}

public JsonEventProperties() {
    throw new UnsupportedOperationException("Not yet implemented");
}

public String getConditon() {
    return conditon;
}

public void setConditon(String conditon) {
    this.conditon = conditon;
}

public String getUsage() {
    return usage;
}

public void setUsage(String usage) {
    this.usage = usage;
}    

}

The result object inside the response for the above case will be:

"result": {"condition":"test","usage":"optional"}

I tried:

mapper.readValue(result,objectClass)

where result is a JsonNode intance of the result (Which for some reason is a LinkedHashMap) and objectClass the class I want it to deserialize to. But this is not working.

I busted my head all day with different ways of doing this but I probably do not understand who Jackson works.

Can anyone help me with this?

Thank you in advance.

alex
  • 705
  • 9
  • 21

3 Answers3

1

I had the same issue, this was my solution.

I added one more field to the object, so when building the object, i am setting the field value with class name, when deserializing it i am using mapper.convertvalue(object, Class.forName(field value)

In your case private Object result;

In the result object add one more field "className", while serializing the class set the value "className" with the name of the class you are treating as result object.

while deserializing the object JsonRpcResponse jsonResp = mapper.readValue(response, JsonRpcResponse.class);

in jsonResp you will have Object result, String className, here the object is of type linkedhashmap

Now to convert to your object

objectmapper.convertValue(result, Class.forName(className))

The above code will get you the generic object which you want .

Hope this helps

krish
  • 31
  • 7
1

Check out jsonrpc4j on github:

https://github.com/briandilley/jsonrpc4j

David Newcomb
  • 10,639
  • 3
  • 49
  • 62
Brian Dilley
  • 3,888
  • 2
  • 24
  • 24
1

I understand the original question to be asking about polymorphic deserialization of the "result" object.

Jackson now has a built-in mechanism available for this, using the @JsonTypeInfo and @JsonSubTypes annotations. (ObjectMapper has methods available as alternatives to using the annotations.) Further information is available in the official docs at http://wiki.fasterxml.com/JacksonPolymorphicDeserialization. Also, I posted a few use examples of this at http://programmerbruce.blogspot.com/2011/05/deserialize-json-with-jackson-into.html.

However, if you're stuck deserializing JSON that, in the target object, does not have an element that identifies the type by some name, then you're stuck with custom deserialization, where you'll have to determine based on some object content what the type should be. One of the last examples in the same blog posted I linked above demonstrates this approach, using the existence of particular JSON elements in the target object to determine the type.

Programmer Bruce
  • 64,977
  • 7
  • 99
  • 97
  • Hi, i am still struggling with the issue of creating an as generic as possible deserilization function for this type of object. I am wondering if I have only the result object (forget the rest) as a JSON String, is there a way to create a method that takes the type of 'result' and returns the result deserialized? For example, if the result is an ArrayList I know i can use TypeReference ''technique to do that. But if for example the result is a CustomObject how will this work? I can not use the TypeReference can I? I would appreciate your feedback. Thank you! – alex Jul 02 '11 at 17:32
  • For a CustomObject you could still use the TypeReference technique. It's not just for generic collections. I posted an example of doing this in my answer to my own question at http://jackson-users.ning.com/forum/topics/deserialize-with-generic-type. This also includes an example of using a contextual deserializer, which for your situation may not be necessary. – Programmer Bruce Jul 02 '11 at 18:58
  • I supose you mean this: TypeReference> fooOfStringType = new TypeReference>() {}; Foo fooOfStringCopy2 = mapper.readValue(fooOfStringJson, fooOfStringType); I think I have tried this bore and did not work. I will try it again. Thank you! – alex Jul 02 '11 at 22:54