Deserializing javabeans objects with gson - android

I'm trying this code, but not working
public class Main {
public static void main(String[] args) { list();}
private static void list() {
Gson gson = new Gson();
String result = "[{\"Person\":{\"id\":\"1\",\"name\":\"Prédio I\"}},{\"Person\":{\"id\":\"2\",\"name\":\"Prédio II\"}}]";
Person[] persons = gson.fromJson(result, Person[].class);
System.out.println("Qtde: " + persons.length);
for (Person pe : persons) {
System.out.println("Name: " + pe.getName());
}
}
}
see that this code takes an array of Persons, but not works, should show me javabens objects

I'm guessing that the problem is with properly binding the JSON structure to a matching Java data structure. Note that each component in the JSON array is an object that has a single property, named "Person", which is an object with two properties, named "id" and "name" -- each component in the JSON array is not a simple Person object, but a Person wrapper object.
The following demonstrates binding the JSON to a matching Java data structure.
import com.google.gson.Gson;
public class GsonFoo
{
public static void main(String[] args)
{
// [{"Person":{"id":"1","name":"Prédio I"}},{"Person":{"id":"2","name":"Prédio II"}}]
String jsonInput = "[{\"Person\":{\"id\":\"1\",\"name\":\"Prédio I\"}},{\"Person\":{\"id\":\"2\",\"name\":\"Prédio II\"}}]";
PersonWrapper[] persons = new Gson().fromJson(jsonInput, PersonWrapper[].class);
System.out.println("Qtde: " + persons.length);
for (PersonWrapper pw : persons)
{
System.out.println("Name: " + pw.Person.name);
}
// output:
// Qtde: 2
// Name: Prédio I
// Name: Prédio II
}
}
class PersonWrapper
{
Person Person;
}
class Person
{
int id;
String name;
}

Related

How to deserialize JSON field with dynamic type?

In a request to the Reddit API, there is a field associated with each post called edited. This field either has a boolean value or if a post has been edited, has a long value which I think is the timestamp of when the post was edited. How can I deserialize this with GSON without knowing the type? If I try to deserialize into a Boolean value I get an exception if a timestamp is present.
Image below of JSON response:
Annotating the dynamic field with #JsonAdapter is probably the easiest way to work around this (assuming you have a DTO class):
final class Datum {
#JsonAdapter(MaybeLongTypeAdapter.class)
final Long edited = null;
}
Where MaybeLongTypeAdapter is as follows:
final class MaybeLongTypeAdapter
extends TypeAdapter<Long> {
private MaybeLongTypeAdapter() {
}
#Override
public void write(final JsonWriter out, final Long value) {
throw new UnsupportedOperationException();
}
#Override
public Long read(final JsonReader in)
throws IOException {
switch ( in.peek() ) {
case NULL:
return null;
case BOOLEAN:
if ( in.nextBoolean() ) {
throw new JsonSyntaxException("Unexpected `true` at " + in);
}
return null;
case NUMBER:
return in.nextLong();
default:
throw new JsonSyntaxException("Unexpected element at " + in);
}
}
}
The type adapter above is pretty self-descriptive. It can be implemented in a more generic way, of course, but it's out of scope here. Additionally, please note that it does not pick the original Long type adapter that can be re-configured in GsonBuilder. Example of use:
private static final Gson gson = new Gson();
private static final Type listOfDatumType = new TypeToken<List<Datum>>() {}.getType();
public static void main(final String... args) {
final String json = "[{\"edited\": false},{\"edited\": 1527130582}]";
final List<Datum> data = gson.fromJson(json, listOfDatumType);
for ( final Datum datum : data ) {
System.out.println(datum.edited);
}
}
Output:
null
1527130582

How to pass JsonArray with no name as request in retrofit body

I want to pass Json array with no name inside Retrofit body but I am getting 400 error.I would like to pass this json array with no name via pojo.Below is the json array that I want to pass.Also I am using PATCH method for this.
[{
"op": "replace",
"path": "/billing_address/line1",
"value": "some other value"}]
I am using following method and in this method I am getting the same response in logcat for list that I wanted but after passing it inside getAuthentionToken I am getting 400 error.
Call<JSONResponse> getAuthentionToken(#Body List obj);
JSONObject jobj = new JSONObject();
jobj.put("op","replace");
jobj.put("path","/billing_address/line1");
jobj.put("value","some other value");
List arrlist = new ArrayList();
arrlist.add(jobj);
apiInterface.getAuthentionToken(arrlist).enqueue(new Callback<JSONResponse>() {
If you are sending data over request body your implementation should be like this:
Define model according to fields (CaseSensitive "Name" -> String Name etc )
set your api function also like that
#POST("/api/geo/getLoc")
public void getFriendsLocation(#Body YourClass classObject, Callback<JsonElement> response);
Use directly your created class object on post request
getFriendsLocation(yourClassObjectThatIncludesFields, new Callback .... );
If your sending data over params You can do this with Gson.
1. Lets say you have a class that have fields like id , number and FriendNumber.Define a function :
public static Map<String, Object> getMapFromObject(Object o) {
Gson gson = new Gson();
Type stringObjectMap = new TypeToken<Map<String, Object>>() {
}.getType();
return gson.fromJson(gson.toJson(o), stringObjectMap);
}
2. set your api function also like that
#POST("/api/geo/getLoc")
public void getFriendsLocation(#QueryMap Map<String, Object>, Callback<JsonElement> response);
When you are sending post request create object from your fields call this function like below here
getFriendsLocation(getMapFromObject(yourClassObjectThatIncludesFields), new Callback .... );
I didnt write whole code which includes class definition and Callback function because they are up to your customization. I assume that you need to send over body so try the first way.
Below is the right answer for me and its work fine.
public class CardUpdate {
public String op;
public String path;
public String value;
public CardUpdate(String op, String path, String value) {
this.op = op;
this.path = path;
this.value = value;
}
public String getOp() {
return op;
}
public void setOp(String op) {
this.op = op;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
#Override
public String toString() {
/*return "CardUpdate{" +
"op='" + op + '\'' +
", path='" + path + '\'' +
", value='" + value + '\'' +
'}';*/
return "{" +'"'+
"op" + '"'+":" +'"' +op + '"'+
"," + '"'+"path" + '"'+":" + '"'+ path + '"'+
"," + '"'+"value" + '"'+":" + '"'+ value + '"'+
'}';
}
}
CardUpdate updatt = new CardUpdate("replace","/billing_address/line1","some other value");
List<CardUpdate> cardddd = new ArrayList<CardUpdate>();
cardddd.add(updatt);

Cart in Android Using Static Class

Hello I am new to android, currently I am trying to build a cart in my application using a static class:
package com.xxxxxx.vendor.helpers;
import org.json.JSONArray;
import org.json.JSONObject;
public class Cart {
public static JSONObject Info;
public static JSONObject Customer;
public static JSONArray Tickets;
public static JSONArray Extras;
}
Now I have a button that is supposed to add a jsonObject to my Tickets JSONArray on button click:
btView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
int qty = Integer.parseInt(tqView.getText().toString());
String tClass = ticketsArr.getJSONObject(finalI).get("class").toString();
String eName = eo.getName();
JSONObject t = new JSONObject();
t.put("id", ticketsArr.getJSONObject(finalI).get("id").toString());
t.put("class", tClass);
String description = tClass + " ticket" + (qty > 1 ? "s" : "") + " to" + eName;
t.put("description", description);
t.put("price", ticketsArr.getJSONObject(finalI).get("fee").toString());
t.put("quantity", qty);
// Cart.Tickets.put(t);
JSONArray tArr = Cart.Tickets;
tArr.put(t);
Toast.makeText(TicketsActivity.this, Cart.Tickets.toString(), Toast.LENGTH_SHORT).show();
} catch (JSONException e) {
e.printStackTrace();
}
}
})
However whenever I click the button the app crashes at this line: tArr.put(t);
I have no idea what I am doing wrong here, although my object oriented is a bit rusty so I may be making a silly mistake somewhere.
This is because Cart.Tickets is null . You have not added anything toCart.Tickets
and hence tArr is null
JSONArray tArr = Cart.Tickets;
You need to assign some value to Cart.Tickets before using it in order to avoid any crashes.

Getting Nested JsonObjects & Arrays Using Retrofit Library

I got tired using this library, this is my first time using it and made a lot of success ways, but i'm a bit confused in getting the following Json :
{
"Guides":
{
"English": {"ArabicSony":"Test1","ArabicNexus":"Test2","ArabicSamsung":"Test3","ArabicHTC":"Test4"}
,"Arabic": {"EnglishSony":"Test1","EnglishNexus":"Test2","EnglishSamsung":"Test3","EnglishHTC":"Test4"}
}
}
Googled and saw a lot of guides and answered, and made my List like this :
public class PostItem {
List<PostItemArabic> Arabic;
List<PostItemEnglish> English;
}
class PostItemArabic{
private String ArabicSony;
private String ArabicNexus;
private String ArabicSamsung;
private String ArabicHTC;
public String getArabicSony() {
return ArabicSony;
}
public void setArabicSony(String arabicSony) {
ArabicSony = arabicSony;
}
public String getArabicNexus() {
return ArabicNexus;
}
public void setArabicNexus(String arabicNexus) {
ArabicNexus = arabicNexus;
}
public String getArabicSamsung() {
return ArabicSamsung;
}
public void setArabicSamsung(String arabicSamsung) {
ArabicSamsung = arabicSamsung;
}
public String getArabicHTC() {
return ArabicHTC;
}
public void setArabicHTC(String arabicHTC) {
ArabicHTC = arabicHTC;
}
}
class PostItemEnglish{
private String EnglishSony;
private String EnglishNexus;
private String EnglishSamsung;
private String EnglishHTC;
public String getEnglishSony() {
return EnglishSony;
}
public void setEnglishSony(String englishSony) {
EnglishSony = englishSony;
}
public String getEnglishNexus() {
return EnglishNexus;
}
public void setEnglishNexus(String englishNexus) {
EnglishNexus = englishNexus;
}
public String getEnglishSamsung() {
return EnglishSamsung;
}
public void setEnglishSamsung(String englishSamsung) {
EnglishSamsung = englishSamsung;
}
public String getEnglishHTC() {
return EnglishHTC;
}
public void setEnglishHTC(String englishHTC) {
EnglishHTC = englishHTC;
}
}
My Model :
private class Model {
private List<PostItem> Guides;
public List<PostItem> getGuides() {
return Guides;
}
public void setGuides(List<PostItem> roms_center) {
this.Guides = roms_center;
}
}
And printing the result like this :
List<PostItem> Guides = response.body().getGuides();
for(int i = 0 ; i < Guides.size() ; i ++ ) {
for (int b = 0; b < Guides.get(i).English.size() ; b++){
Log.LogInfo("English Result Is: " + Guides.get(i).English.get(i).getEnglishHTC());
Log.LogInfo("English Result Is: " + Guides.get(i).English.get(i).getEnglishNexus());
Log.LogInfo("English Result Is: " + Guides.get(i).English.get(i).getEnglishSamsung());
Log.LogInfo("English Result Is: " + Guides.get(i).English.get(i).getEnglishSony());
}
for (int b = 0; b < Guides.get(i).Arabic.size() ; b++){
Log.LogInfo("Arabic Result Is: " + Guides.get(i).Arabic.get(i).getArabicHTC());
Log.LogInfo("Arabic Result Is: " + Guides.get(i).Arabic.get(i).getArabicNexus());
Log.LogInfo("Arabic Result Is: " + Guides.get(i).Arabic.get(i).getArabicSamsung());
Log.LogInfo("Arabic Result Is: " + Guides.get(i).Arabic.get(i).getArabicSony());
}
}
My work isn't correct, and getting a lot of errors,
Here's the last error i got :
`Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 3 column 18 path $.Guides
What's the way to make it correct ? `
Based on your models when you try to get the guides list your telling retrofit to populate an array. Retrofit is then getting the data and finding that it is a single object and not array. So you need to update your model to reflect the data returned. For example:
class PostItem {
List<Language> mLanguages;
}
class Language{
String mLanguageTitle; //for example english
List<String> mData; //for this is your list of data
}
Then in your activity instead of getting guides you would get just a post item for example:
response.body().getPostItem();
Hope it helps !
First of all, you can use the retrofit Gson library.
You can handle this in two ways:
Option 1: reformat your languages in your json to be an array like Doug says.
{
"Guides":
[
{"Lang":"English","ArabicSony":"Test1","ArabicNexus":"Test2","ArabicSamsung":"Test3","ArabicHTC":"Test4"}
, {"Lang":"Arabic","EnglishSony":"Test1","EnglishNexus":"Test2","EnglishSamsung":"Test3","EnglishHTC":"Test4"}
]
}
Then you will need to redesign your class to reflect this structure.
Like Doug sayd:
class PostItem {
List<Language> mLanguages;
}
Option 2: Create a custom json desirializer in your class. this will take the Json and break it down into whatever structure you want it to be.
public class PostItem implements JsonDeserializer
#Override
public MyDesirializer deserialize(JsonElement json, Type type,
JsonDeserializationContext context) throws JsonParseException {
JsonObject jarabic = (JsonObject) json.get("Arabic");
//whatever manipulations you want to do (fill with your own code)
PostItem item = new PostItem();
item.arabic = jarabic;
...
...
return item;
}

Flatten Nested Object into target object with GSON

Dearest Stackoverflowers,
I was wondering if anyone knows how to solve this the best way;
I'm talking to an api which returns a json object like this:
{
"field1": "value1",
"field2": "value2",
"details": {
"nested1": 1,
"nested2": 1
}
In java I have an object (entity) which for example, would have all these fields, but with the details as loose fields, so:
field1, field2, nested1, nested2.
This because It's an android project and I can't just go saving a class with info into my entity since I'm bound to ormlite.
Is there any way to convert the fields flat into my object using GSON? note that I'm using a generic class to convert these right now straight from the API. And I want to store these fields (which contain information as an int). In the same entity.
You can write a custom type adapter to map json value to your pojo.
Define a pojo:
public class DataHolder {
public List<String> fieldList;
public List<Integer> detailList;
}
Write a custom typeAdapter:
public class CustomTypeAdapter extends TypeAdapter<DataHolder> {
public DataHolder read(JsonReader in) throws IOException {
final DataHolder dataHolder = new DataHolder();
in.beginObject();
while (in.hasNext()) {
String name = in.nextName();
if (name.startsWith("field")) {
if (dataHolder.fieldList == null) {
dataHolder.fieldList = new ArrayList<String>();
}
dataHolder.fieldList.add(in.nextString());
} else if (name.equals("details")) {
in.beginObject();
dataHolder.detailList = new ArrayList<Integer>();
} else if (name.startsWith("nested")) {
dataHolder.detailList.add(in.nextInt());
}
}
if(dataHolder.detailList != null) {
in.endObject();
}
in.endObject();
return dataHolder;
}
public void write(JsonWriter writer, DataHolder value) throws IOException {
throw new RuntimeException("CustomTypeAdapter's write method not implemented!");
}
}
Test:
String json = "{\"field1\":\"value1\",\"field2\":\"value2\",\"details\":{\"nested1\":1,\"nested2\":1}}";
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(DataHolder.class, new CustomTypeAdapter());
Gson gson = builder.create();
DataHolder dataHolder = gson.fromJson(json, DataHolder.class);
Output:
About TypeAdapter:
https://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/TypeAdapter.html
http://www.javacreed.com/gson-typeadapter-example/

Categories

Resources