Retrofit GSON Parsing Arraylist Inside of Object - java

I have a json object like this:
{
products:[
{
name:Prod1,
quantity:3
},
{
name:Prod2,
quantity:1
}
]
}
I have my gson object like so:
public class Product{
#SerializedName("name")
public String name;
#SerializedName("quantity")
public int quantity;
}
When I set up my retrofit with something like this
#GET("/products")
void getProducts(Callback<ArrayList<Product>> c);
It will fail, obviously, because that array isn't the root object. Is there a simple way to force this to dig down into the json one level before parsing that ArrayList, or am I going to have to create a whole GSON adapter to accomplish this?

I accomplished this by creating and using my own custom deserializer. The code is simpler than a full Gson Adapter, but accomplishes what I need.
https://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/JsonDeserializer.html

Related

Gson why does my deserialization not work?

I am trying to make a java program that will need to work with json, I have choose gson as my library to handle managing JSON
But when I try to deserialize my json the messagereturn.text value and the messagereturn.extra.text value both get set as null, I have tried to fix this but I am unable to.
An example of the json that i am trying to deserialize is
{
"text":"",
"extra":[{
"text":"eee joined the game",
"color":"yellow"
}]
}
And this is how I am calling gson
Message messagepacket = event.<ServerChatPacket>getPacket().getMessage();
//this gets the json data
messagereturn messagereturn = gson.fromJson(String.valueOf(messagepacket), messagereturn.class);
System.out.println(messagereturn.returnmethod());
Here is the class I am trying to deserialize too
public class messagereturn {
String text;
public class extra{
String text;
}
public String returnmethod() {
extra extra = new extra();
return text + extra.text;
}
}
Thank you, if there is any more informaton needed let me know, thanks
There is a problem understanding your JSON (and creating the Java classes by the way). These marks [] means that is a list.
So you have an object with atributes text, type String and extra, type List<Object>.
This list contains another object (note that the object is defined by {} and list by []).
The object into the list has another two attributes: text and color both with primitive types; String.
So your java class should be like this:
public class Messagereturn {
private String text;
private List<Extra> extra;
//getters and setters and other methods
}
And the class Extra:
public class Extra {
private String text;
private String color;
//getters and setters
}
With this data model you can call your Gson with these structure.
Also, you don't need to call returnMethod to create Extra object, it is created by Gson.
Using this line of code:
Messagereturn mr = new Gson().fromJson(txt, Messagereturn.class);
And your JSON example, this is the value stored when run in debug mode:
As you can see, tha values from JSON has been created and loaded into memory.

Gson, Deserialize Wrapper class

I need help with the gson library, basically i have to de-serialize a wrapper class defined like this:
static class WrapperClass {
public int value;
private final String otherData;
public WrapperClass(String otherData) {
this.otherData = otherData;
}
}
The class that I have to "jsonize" has fields like this:
private final WrapperClass wrappedData = new WrapperClass("other data");
The serializer of the wrapper class is really simple:
#Override
public JsonElement serialize(WrapperClass src, Type typeOfSrc, JsonSerializationContext context) {
return context.serialize(src.value);
}
The problem is the de-serialization side, I should not re-instantiate the WrapperClass object because it's already there by default, i have only to de-serialize it's value, it's possible to this with the gson library?
So, what you want to do: "read" the content of some JSON string and "overlay" existing objects with that.
I am not aware of a built-in way to do that. Beyond that: doing something of this complexity under the covers sounds like the wrong approach, too.
Thus, my recommendation: clearly separate those responsibilities. Meaning: instead of of creating a (almost counter-intuitive) solution that merges JSON data "into" existing objects: do that explicitly, it step by step. Like:
read the JSON data and de-serialize into one or more objects
then have an another special component "update" your "old" objects with the information found in the de-serialized objects

Specifying a class that uses T

I'm using a method that takes a Class<T> as a parameter.
The class I want to pass as a parameter also uses T. It is declared as public class MyObject<T> and has a member declared as public T mMyVar; I then have 2 classes I sometimes use for mMyVar called MyVarObject1 and MyVarObject2.
Example:
private class MyObject<T> {
public T mMyVar;
}
private class MyVarObject1 {
// some variables
}
private class MyVarObject2 {
// some variables
}
Specifically, the method I'm invoking is the JacksonUtil method fromJsonArray.
I'm not sure of the proper syntax here. JacksonUtil needs to know the exact model structure so it can parse the json, but I'm having trouble figuring out the proper syntax for this line:
MyObject<MyVarObject1> result = JacksonUtil.fromJsonArray(jsonStr, MyObject<MyVarObject1>.class);
What I have there doesn't work. My IDE selects the second parameter and says, "Cannot select from parameterized type."
I had a same problem while using with retrofit, This is my solution -
public class ResponseDS<T> {
public int s;
public String e;
public T d;
}
And if you need array of object then,
public class ResponseDSs<T> {
public int s;
public String e;
public T[] d;
}
And below is how I am using it for Retrofit -
Call<ResponseDS<UserDS>> userModelCall = ZivaUtils.getRetrofit().getUser();
I think you have the same problem, hope my solution will help you :)
I do TypedToken from Gson to parse custom objects, I think you can find something similar to use with Jackson, i will edit my answer if i find something later.
You may use TypeToken to load the json string into a custom object.
Gson gson = new Gson();
//This is an example, you probably get this from your server as Json String
MyObject<MyObject1> user = new MyObject<MyObject1>();
String myObjectAsString = gson.toJson(user);
//then parse into your custom object
MyObject other = gson.fromJson(myObjectAsString, new TypeToken<MyObject<MyObject1>>(){}.getType());

Is it possible to deserialize JSON property names with periods as a nested object using GSON?

This is an example of the kind JSON I'm trying to consume using GSON:
{
"person": {
"name": "Philip"
"father.name": "Yancy"
}
}
I was wondering if it were possible to deserialize this JSON into the following structure:
public class Person
{
private String name;
private Father father;
}
public class Father
{
private String name;
}
So that:
p.name == "Philip"
p.father.name == "Yancy"
Currently I am using #SerializedName to obtain property names containing a period, e.g.:
public class Person
{
private String name;
#SerializedName("father.name")
private String fathersName;
}
However, that's not ideal.
From looking at the documentation it doesn't appear to be immediately possible but there may be something I have missed - I'm new to using GSON.
Unfortunately I cannot change the JSON I'm consuming and I'm reluctant to switch to another JSON parsing library.
As far as I understand you can't do it in a direct way, because Gson will understand father.name as a single field.
You need to write your own Custom Deserializer. See Gson user's guide instructions here.
I've never tried it, but it doesn't seem to be too difficult. This post could be also helpful.
Taking a look at Gson's user guide and the code in that post, you'll need something like this:
private class PersonDeserializer implements JsonDeserializer<Person> {
#Override
public Person deserialize(JsonElement json, Type type,
JsonDeserializationContext context) throws JsonParseException {
JsonObject jobject = (JsonObject) json;
Father father = new Father(jobject.get("father.name").getAsString());
return new Person(jobject.get("name").getAsString(), father);
}
}
Assuming that you have suitable constructors...
And then:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Person.class, new PersonDeserializer());
Gson gson = gsonBuilder.create();
Person person = gson.fromJson(jsonString, Person.class);
And Gson will call your deserializer in order to deserialize the JSON into a Person object.
Note: I didn't try this code, but it should be like this or something very similar.
I couldn't do this with just Gson. I need a new library 'JsonPath'. I used Jackson's ObjectMapper to convert the object to string but you can easily use Gson for this.
public static String getProperty(Object obj, String prop) {
try {
return JsonPath.read(new ObjectMapper().writeValueAsString(obj), prop).toString();
} catch (JsonProcessingException|PathNotFoundException ex) {
return "";
}
}
// 2 dependencies needed:
// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
// https://mvnrepository.com/artifact/com.jayway.jsonpath/json-path
// usage:
String motherName = getProperty(new Person(), "family.mother.name");
// The Jackson can be easily replaced with Gson:
new Gson().toJson(obj)

How to handle json with different type but same key in jackson

I request a rest service where the json result holds a list of place objects o just one place object but both with the same key:
{
place:[{lat:12, lon:12}, {lat:12, lon:12}]
}
or
{
place: {lat: 12, lon:12}
}
Is there a way to handle this with the jackson json parser to I've got always a list of objects?
Sure. Have you tried it? For first example, it would seem like your object model would be something like:
public class Places {
public List<Place> place:
}
public class Place {
public int lat, lon;
}
and you would get expected JSON.

Categories

Resources