In my backend I have a class User which has multiple Trips.
Those trips have multiple user.
This is a circular reference.
I use this code in my rest service to serialize the user object:
Gson gson = new Gson();
return gson.toJson(user, TripUser.class);
In my android app I do the following:
Gson gson = new Gson();
TripUser Tuser = gson.fromJson(data, TripUser.class);
return Tuser;
What can I do about the circular reference exception?
Is there another way to make this work?
You should try to use flexjson 2.1
This would solve your problem because you can chose which items he should serialize to Json etc.
Also this library gives no problems with circular references
I am not fully sure , but u can try like this :
Gson gson = new Gson();
Type type = new TypeToken<TripUser>(){}.getType();
TripUser user = (TripUser) gson.fromJson(data, type);
Related
json want to parse and display link
that Is a response.body of Okhttp and I want parse and display it
Create a Java class that has the same structure as that jsonBody then Using gson library (add this to gradle implementation 'com.google.code.gson:gson:2.8.2') you can simply do this
JSONObject jsonObject = new JSONObject(response.body().string());
Gson gson = new Gson();
YourCLass yourClass = gson.fromJson(jsonObject.toString(), YourCLass .class);
I am calling a REST service (not mine) using retrofit which either returns a list of objects (if there are multiple) or a single object (if one). I was able to find a similar issue here however the suggestion is to change the API which i don't have control of. I also read this thread which seems to be a good approach but is there a way to handle this using Retrofit?
While the answer from #pirho seems to be applicable, I found out a different and simple solution which worked for me. Hopefully it may help others as well.
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(JacksonConverterFactory.create(mapper))
.client(okHttpClient)
.build();
You can get the API response data as Map<String, JsonElement> in response and then parse it based on your requirement directly. As you can check here if JsonElement is JsonArray
for ex:
public fun parseData(val jsonElement:JsonElement){
val gson = Gson()
if(jsonElementFromServer.isJsonArray()){
//here you can just parse it into some list of array
}else{
//here you can parse using gson to single item element or model
}
}
JsonElement ref
Using Gson to get list of items or single model
As the author of the 2nd post you referred I also refer to the implementation of PostArrayOrSingleDeserializer described in that answer of mine.
When using Gson with Retrofit (Retrofit's converter-gson) you just need to register the adapter with custom Gson instance and build the Retrofit instance with that Gson instance, see below example helper class:
public class MyRetrofit {
public static MyAPI getMyApi() {
Gson gson = new GsonBuilder()
.registerTypeAdapter(Object.class,
new ObjectArrayOrSingleDeserializer())
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://example.org")
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
return retrofit.create(MyAPI.class);
}
}
So the Object in the JsonDeserializer named ObjectArrayOrSingleDeserializer is the DTO you need to check for single instance or array. Replace Object with corresponding DTO and modify deserializer accordingly.
Given the following code:
final class retVal { int photo_id; }
Gson gson = new Gson();
retVal ret = gson.fromJson("{\"photo_id\":\"383\"}", retVal.class);
I get ret set to null.
I'm sure I've missed something obvious out, as toJson with a class also fails, although hand-construction through JsonObject works.
Declare your class retVal outside the method.
Gson helps you to serialize objects. So, you need an object first. Based on your approach, you want to do something like
RetVal myRetVal = new RetVal();
Gson gson = new Gson();
String gsonString = gson.toJson(myRetVal);
To retrieve the object back from the string:
Gson gson = new Gson();
RetVal myNewRetValObj = gson.fromJson(gsonString, RetVal.class);
I want to create json data of format like this:
{
"Credential":{
"ref1":"Test",
"ref2":"test",
"ref3":"test"
},
"ref4":"data"
}
I tried a lot, but i did not find a way to do this. Can anyone please help me.
EDIT:
I am able to put the data like below:
{
"ref1":"Test",
"ref2":"test",
"ref3":"test"
}
Thanks in advance.
You can always use JSONStringer class to do so,
JSONStringer jsonstr = new JSONStringer()
.object().key("Credential")
.object().key("ref1").value("Test")
.key("ref2").value("test")
.key("ref3").value("test")
.endObject()
.key("ref4").value("data")
.endObject();
Log.i("JSONStringer", jsonstr.toString());
why do not you use google gson?
// get Json string
Gson gson = new Gson();
String strJson = gson.toJson(yourObject);
Is not it a better solution?
I am facing an issue with Deserializing a POJO object.
Following is the structure of the POJO objects on the Service side.
Class Ball{
int field1;
int field2;
}
Class BaseBall extends Ball
{
int field3;
int field4;
}
Class BallList{
List<Ball> balls;
}
Even on the Android Client side, i have a similar structure for the POJO objects.
Code for Android Client:
RestTemplate restTemplate = new RestTemplate();
List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
acceptableMediaTypes.add(new MediaType("application","json"));
HttpHeaders headers = new HttpHeaders();
headers.setAccept(acceptableMediaTypes);
HttpEntity<String> entity = new HttpEntity<String>(headers);
ResponseEntity<BallList> response = restTemplate.exchange(
url, HttpMethod.GET, entity, BallList.class);
if(response.getStatusCode() == HttpStatus.OK)
{
result += "OK";
}
04-13 18:17:46.127: ERROR/AndroidRuntime(4359): Caused by: org.springframework.web.client.ResourceAccessExcep tion: I/O error: Unrecognized field "filed3" (Class com.xx.yy.model.Ball), not marked as ignorable
On the service side, i am providing the baseball list as a response. Can anyone point me to a solution please.
This is not really Android problem. The system looks at your stuff from Ball level and hence you get Unrecognized field "field3" exception. Also I would declare acceptibleMediaType as ArrayList since List is not serializable.
I would try to create and send ArrayList<BaseBall> just to see if it works and then go from there
Spring Recently released (3.2.0.RELEASE) and they added MappingJackson2HttpMessageConverter which solved a similar problem I had. MappingJackson2HttpMessageConverter uses Jackson 2 for deserialization while MappingJacksonHttpMessageConverter uses pre-2.0 Jackson. Try adding following converter to your RestTemplate and give it a shot.
MappingJackson2HttpMessageConverter map = new MappingJackson2HttpMessageConverter();
messageConverters.add(map);
restTemplate.setMessageConverters(messageConverters);