Gson deserialisation returns null - json

I have a problem on converting JSON string to object in Android. Here are the JSON structure and Java classes:
JSON:
{
"code":"SUCCEED",
"message":"",
"result":{
"ccahUserId": 111,
"ccahUserName":"your_name",
"userFirstName":"your_first_name",
"userLastName":"your_last_name",
//others
}
Java classes:
public class Result<T>{
public String code;
public String message;
public T result;
}
public class DeviceSetting
{
public long ccahUserId;
public String ccahUserName;
public String userFirstName;
public String userLastName;
//other members
}
Activity:
Gson gson = new Gson();
Result<DeviceSetting> setting = gson.fromJson(result, Result<DeviceSetting>.class);
When I deserialise the JSON string, code and message field were good but result field is null.
I am not familiar with Gson yet, so please help how to fix this problem?
Thanks in advance.

Likely the result field is null because it relies on the type parameter for Result.
From the GSON documentation for Gson.fromJson(JsonElement, Class<T>) (bolding is mine):
This method deserializes the Json read from the specified parse tree
into an object of the specified type. It is not suitable to use if the
specified class is a generic type since it will not have the generic
type information because of the Type Erasure feature of Java. Therefore, this method should not be used if the desired type is a generic type. Note that this method works fine if the any of the fields of the specified object are generics, just the object itself should not be a generic type. For the cases when the object is of generic type, invoke fromJson(JsonElement, Type).

Related

validating a JSON list as the root object with spring mvc

I need to validate a JSON list similar to the following:
[{"op":"A","path":"C","value":"B"},...]
in a Spring MVC application - I am currently deserializing (using default Jackson) to an object along the lines of:
public class Operations extends ArrayList<Operation>{}
public class Operation {
#NotEmpty
public String op;
#NotEmpty
public String path;
public Object value;
public void setOp(String op)... and other getters/setters
}
but I cannot figure out how to get jsr303 validation provided by reference hibernate implementation to fire for the attributes of Operation.
I can get it to function if I wrap the list in a class but then I have an incorrect format for the JSON, ie something like:
{"ops":[{"op":"A",...},...]}
is it possible to validate the first object (Operations)? and if not is it possible to serialize the first format (ie the JSON list) to an object of the second format (ie a list wrapped in a placeholder object with a placeholder field)
Update
Having failed to find a way to trigger the jsr303 validation on a bare ArrayList I have written a custom jackson json deserializer to stick it into a containing object with an annotated field along the lines of
#JsonDeserialize(using=OperationsDeserializer.class)
public class Operations {
#NotEmpty
private ArrayList<Operation> ops;
public void setOps(ArrayList<Operation>ops)...
public ArrayList<Operation> getOps()...
}
This works but now any autogenerated documentation for my api is generating json examples with the dummy "ops" field in it - ie {"ops" : [ ... ] }
so the search for a method of triggering jsr303 validation on an ArrayList that is not a field of another object continues - perhaps there is a way to inject a proxy wrapping class at runtime that might work around this?
Use ObjectMapper.class. it has a method which will convert Json Object into Class Object
method is , new ObjectMapper().readValue(String str, Class<T> valueType)
So you can iterate your Object array, convert to string and pass it to this method to get your result.
so it would look like,
new ObjectMapper().readValue(object.toString, Operation.class);

JAX-RS / Jersey ".get(Integer.class)" and single JSON primitive (Integer) values?

I have a JAX-RS WebService with the following method:
#Path("/myrest")
public class MyRestResource {
...
#GET
#Path("/getInteger")
#Produces(APPLICATION_JSON)
public Integer getInteger() {
return 42;
}
When accessed using this snipped:
#Test
public void testGetPrimitiveWrapers() throws IOException {
// this works:
assertEquals(new Integer(42), new ObjectMapper().readValue("42", Integer.class));
// that fails:
assertEquals(new Integer(42), resource().path("/myrest/getInteger").get(Integer.class));
}
I get the following exception:
com.sun.jersey.api.client.ClientResponse getEntity
SEVERE: A message body reader for Java class java.lang.Integer, and Java type class java.lang.Integer, and MIME media type application/json was not found
com.sun.jersey.api.client.ClientResponse getEntity
SEVERE: The registered message body readers compatible with the MIME media type are: application/json
...
The problem is just with returning single primitive values (int/boolean) or their wrapper classes. Returning other POJO classes is not the problemen so I guess all the answers regarding JSONConfiguration.FEATURE_POJO_MAPPING and JAXB annotations do not apply here.
Or which annotation should I use to describe the return type if I don't have access to its
class source?
Using ngrep I can verify that just the String "42" is returned by the webservice. Thats a valid JSON "value" but not a valid JSON "text" according to the spec. So is my problem on the client or the server side?
I tried activating JSONConfiguration natural/badgerfish according to http://tugdualgrall.blogspot.de/2011/09/jax-rs-jersey-and-single-element-arrays.html but with no success (ngrep still shows just "42"). Would that be the right path?
Any ideas are appreciated!
This is a recognized bug in Jackson, which has been touted (incorrectly in my opinion) as a feature. Why do I consider it a bug? Because while serialization works, deserialization definitely does not.
In any case, valid JSON cannot be generated from your current return type, so I would recommend creating a wrapper class:
class Result<T> {
private T data;
// constructors, getters, setters
}
#GET
#Path("/getInteger")
#Produces(APPLICATION_JSON)
public Result<Integer> getInteger() {
return new Result<Integer)(42);
}
Alternatively, you can elect to wrap root values, which will automatically encapsulate your data in a top level JSON object, keyed by the objects simple type name - but note that if this option is used that all generated JSON will be wrapped (not just for primitives):
final ObjectMapper mapper = new ObjectMapper()
.configure(SerializationFeature.WRAP_ROOT_VALUE, true)
.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
final String serializedJson = mapper.writeValueAsString(42);
final Integer deserializedVal = mapper.readValue(serializedJson,
Integer.class);
System.out.println(serializedJson);
System.out.println("Deserialized Value: " + deserializedVal);
Output:
{"Integer":42}
Deserialized Value: 42
See this answer for details on how to retrieve and configure your ObjectMapper instance in a JAX-RS environment.

Simplest custom serialization in Jackson?

I have an EntityId class that servers as a simple wrapper class to database identifiers. The class already has methods for converting to and from a string representation. I'd like to use this string representation of the EntityId in my JSON web resources.
What's the simplest to implement custom serialization for this simple type in Jackson? I know I can write a custom serializer and deserializer, but I wondered if there might be an even simpler solution.
Thanks!
If there is a method to serialize type as String, you can just add #JsonValue annotation like so:
public class MyClass {
#JsonValue public String toString() { return "xxx"; }
}
Conversely, if there is a single-arg constructor that takes a String, int or long (or some Java type that Jackson can convert to from JSON Scalar type), you can add #JsonCreator annotation next to that constructor:
public class MyClass {
#JsonCreator
public MyClass(OtherPojo value) { // or use 'Map<String,Object>', extract data
// ...
}
}

Configure ServiceStack.Text to throw on invalid JSON

Is it possible to make the ServiceStack.Text library throw when attempting to deserialize invalid JSON. By default it looks as if invalid JSON is just ignored, so that the result object contains null values.
When I attempt to deserialize this json (a " is missing after MongoConnectionString)
{
"MongoDb": {
"MongoConnectionString:"mongodb://localhost:27017/x",
"MongoDatabase":"x",
"MongoSafeModeEnabled":true,
"MongoSafeModeFSync":true,
"MongoSafeModeWriteReplicationCount":
"MongoSafeModeWriteTimeout":"00:00:00"
},
by doing this: JsonSerializer.DeserializeFromString(json);
where
public class Configuration {
public class MongoDbSettings
{
public string MongoConnectionString {get;set;}
public string MongoDatabase {get;set;}
public bool MongoSafeModeEnabled {get;set;}
public bool MongoSafeModeFSync {get;set;}
public int MongoSafeModeWriteReplicationCount {get;set;}
public TimeSpan MongoSafeModeWriteTimeout {get;set;}
}
}
I get a Configuration object where MongoDbSettings is null. I would prefer to get an exeception in this case. Is this possible?
At the moment the ServiceStack serializers are optimized for resilience, i.e. deserialize as much as possible without error.
I'd recommend adding some of your own validation checking post serialization to work out which fields weren't deserialized correctly.
You could also submit a pull-request to the ServiceStack.Text project that supports an opt-in flag (i.e. on JsConfig) to change the behavior to throw exceptions.

How to serialize JSON with Object containing both primitives and List<> types?

So I have a class that I was planning on using for simple JSON serialization.
public class Thing {
private int field1;
private String some_other_field;
private List<SubType> subs;
private list<AnotherType> another;
public String toJson() {
Gson g = new Gson();
g.toJson(this);
}
}
So the documentation shows that if you want to serialize generic types, you need to specify a TypeToken:
Type listtype = new TypeToken<List<SubType>>() {}.getType();
gson.toJson(subs, listtype);
But then, how does this work if I have a whole class I want to serialize for? Where do I get to specify the serialization type for those two List<> types so that I can just pass the whole object in and get a serialized output? Is that even possible?
From the doc it seems that if you serialize a complete object with toJson(...), it deals with the generics attributes properly.
toJson(Object)
"Note that this method works fine if the any of the object fields are of generic type, just the object itself should not be of a generic type"
What output did you get with your object ?