I have JSON string
For Example
[{
"id":"abc",
"name":"ffa",
"done":0
},
{
"id":"abc",
"name":"ffa",
"done":0
}]
I want to convert this JSON to collection of Examp class.
I've tried use gson.
public static void main(String[] args)
{
Gson gson = new Gson();
Examp a=new Examp(); //Class Examp have 3 fields (id,name,done)
Examp b=new Examp();
a.done=0;
b.done=0;
a.id="foo";
b.id="foo1";
a.name="faa";
b.name="faa1";
ArrayList<Examp> arr= new ArrayList<Examp>();
arr.add(b);
arr.add(a);
String str = gson.toJson(arr);
System.out.println(str); //format check
ArrayList<Examp> collection = gson.fromJson(str, ArrayList.class);
}
At this moment the type of data in collection isn't Examp, but LinkedTreeMap.
I have one question.
How can I access this data (for example name)?
You need a TypeToken
ArrayList<Examp> collection = gson.fromJson(str, new TypeToken<ArrayList<Examp>>(){}.getType());
The TypeToken is kind of a generic hack to get the generic type argument of a generic type use.
Note that you won't be able to use TypeToke with type variables. (You'll be able to use it, but won't get what you want/expect).
You need to use TypeToken:
Type type = new TypeToken<ArrayList<Examp>>() {}.getType();
List<Examp> collection = gson.fromJson(json, type );
Reference on their wiki page:
Related
I'm trying to build json using Gson dynamically as following ,
loop through existing fields and take the name and value and build json based on it,
so for an input:
a="AString"
B=true
C=null
D=[1,2,3]
E={"a":"b"}
will get valid json as:
{
"a":"AString",
"b": true,
"c": null,
"d":[1,2,3],
"e":{"a":"b"}
}
code:
JsonObject jsonObject = new JsonObject();
Field OutPortList[] = BBClass.class.getDeclaredFields();
for(Field x : OutPortList)
{
jsonObject.addProperty( x.getName() , x.get(this));
}
Getting error :
jsonObject.addProperty( String , String ) is not applicable
also tried casting :
jsonObject.addProperty( x.getName() , x.getType().cast(x.get(this)) );
Not sure but i guess it relate to type ,
as i try with x.get(this).toString() and its work but this will cast everything to string type.
I'm not sure what would be the correct way to handle the type automatically without casting it each time to the correct type.
You are trying to squeeze a java.lang.Object into a JsonElement (the add method) or a String (the addProperty method). The type of the field could be anything, including types that have no direct counterpart in json.
The easiest way would be to rely on the marshalling gson provides.
Gson gson = new Gson();
gson.toJson( this );
which yields a json formatted string.
If for some reason you still want to iterate the fields manually, you could still use gsons type marshalling for building the properties. Like this:
JsonObject jsonObject = new JsonObject();
Field[] OutPortList = Test.class.getDeclaredFields();
Gson gson = new Gson();
for(Field x : OutPortList)
{
jsonObject.add( x.getName(), gson.toJsonTree( x.get(this) ) );
}
Note, that you should consider sticking to Java naming conventions by using lowerCamelCase on variable names.
Is is mandatory to use TypeToken (as recommended in the Gson doc) as type when converting a list into json like below -
new Gson().toJson(dateRange, new TypeToken<List<String>>() {}.getType());
For me below code is also working -
new Gson().toJson(dateRange, List.class);
Just want to make sure that code doesn't break.
As per docs -
If the object that your are serializing/deserializing is a
ParameterizedType (i.e. contains at least one type parameter and may
be an array) then you must use the toJson(Object, Type) or
fromJson(String, Type) method. Here is an example for serializing and
deserializing a ParameterizedType:
Type listType = new TypeToken<List<String>>() {}.getType();
List<String> target = new LinkedList<String>();
target.add("blah");
Gson gson = new Gson();
String json = gson.toJson(target, listType);
List<String> target2 = gson.fromJson(json, listType);
This is the special case, in other cases you can use class type directly.
For reference - http://google.github.io/gson/apidocs/com/google/gson/Gson.html
Hope this helps
my json object starts with an object, then contains an array of the object I want { "myObjectArray":[ {....} , {....} , {....} ] }, I have made the model file for the object represented in {....} , how do I get this generic collection code to not assume my root element is an array without making a new nested object file
This is what I currently have,
Type listType = new TypeToken<List<T>>() {
}.getType();
List<T> yourClassList = new Gson().fromJson(jsonArray, listType);
but this assumes that my json object is constructed like this [{....}, {....}, {....}] instead of the way I detailed above
Therefore, parsing returns a JsonSyntaxException
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2
Without creating a pointless model object that contains one variable "myObjectArray" which contains a List of myObject , how would I modify a GSON builder to accomodate?
(I am using android so I can't use a lot of the Oracle JVM reflection methods, including ParameterizedTypeImpl)
using
GsonBuilder builder = new GsonBuilder();
mGson = builder.enableComplexMapKeySerialization().create();
listType = new TypeToken<Map<String, List<T>>>() {}.getType();
parsedGSON = mGson.fromJson(reader, listType);
is the answer
GSON creates a LinkedTreeMap object
I have JSON like this:
{"foos":[{"id":1}, {"id":2}]}
I can turn it into List<Foo> pretty simply with GSON, like this:
Type t = new TypeToken<List<Foo>>(){}.getType();
JsonObject resp = new Gson().fromJson(
new JsonParser().parse(json).getAsJsonObject().get("foos",t);
But let's assume that I also have another JSON, where the name of the array and type changes
{"bars":[{"id":3},{"id":9}]}
Of course I could just swap the "foos" parameter for "bars", but if it's possible, I'd like my software to do it for me.
Is there a way to extract the name of the array child with the GSON library?
I'm not sure if I understood what you want correctly, but aren't you referring to the use of generics? I mean you could write a method that returns you a List of your relevant class? Something along the lines of
Type type = new TypeToken<List<MyClass>>() {}.getType();
List<MyClass> myObjects = getMyObjects(new JsonParser().parse(json).getAsJsonObject().get("foos"), type);
public static List<T> getMyObjects(String jsonString, Type type) {
Gson gson = new Gson();
List<T> myList = gson.fromJson(jsonString, type);
return myList;
}
Looking at your JSON examples, I assume that the name of the list element can change, but not the content of the list. If this is correct, you could parse your JSON response just like this:
Type mapType = new TypeToken<Map<String, List<Foo>>>() {}.getType();
Map<String, List<Foo>> map = gson.fromJson(jsonString, mapType);
And then you can access the name of the list with:
String listName = map.keySet().iterator().next();
If the content of the list could also change, things get a bit more complicated...
this is JSON string 1
{"title":["1","2"], "amount":["1","2"]}
this is JSON string 2
{"title":"", "amount":""}
string 1 is created when I enter values in form and string 2 is created when I dont,
I want to know if the string is in format 1 that is title is an array ["1", "2"] or format 2 that is title is just a string "" on the server side in a servlet, before I parse it. is there any way of doing so?
this is my previous question,
How do I parse this JSON string using GSON in servlet
which is solved but as you can see there i have class Data which has instance variables of type ArrayList, so when I parse it with this line
Data data = gson.fromJson(param, Data.class);
it throws exception
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING at line 1 column 24
because as I have declared ArrayList, it expects array only in json to parse it without any exceptions....but when I dont enter values in my form it doesnt create json string as
{"title":[], "amount":[]}
rather it creates like this
{"title":'', "amount":''}
which has string as value, which causes parsing to throw exception
Had this problem as well and this is how I got around it
In your Data object have
public class Data {
// This is a generic object whose type is determined when used by GSON
private Object title;
// get the type of object and return as string
public String getTitleObjType() {
String objType = title.getClass().toString();
return objType;
}
// used if the object is an ArrayList, convert into an ArrayList<Object>
public ArrayList<String> getTitleArrayList() {
// Turn the Object into an arraylist
#SuppressWarnings("unchecked") // This is to counter the fact that the cast is not type safe
ArrayList<String> titleArrayList = (ArrayList<String>) title;
return titleArrayList;
}
// used if the object is not an array
public String getTitleStr() {
return title.toString();
}
}
When GSON builds the object it will create and each of these to be either a String or an ArrayList
Then when you want to use the objects, test to see what they are
ArrayList<String> titleValArrayList = new ArrayList<String>();
String titleValStr = "";
if(getTitleObjType.equals("class java.util.ArrayList")) {
titleValArrayList = getTitleArrayList();
//do whatever you like
}
else if(getTitleObjType.equals("class java.util.String")) {
titleValStr = getsTitleStr();
//do whatever you like
}
Check Google GSON it allows you to parse JSON server side.
It goes something like this:
String jsonString = request.getParameter("jsonParemeter");
Gson gson = new Gson();
Map fromJsonMap = gson.fromJson(jsonString, HashMap.class);
Object object = fromJsonMap.get("title");
if (object instanceof Collection) {
// then is it's your array
}
else {
// it's not
}
If, for example, I run the following example code:
String json1 = "{\"title\":[\"1\",\"2\"], \"amount\":[\"1\",\"2\"]}";
String json2 = "{\"title\":\"\", \"amount\":\"\"}";
Gson gson = new Gson();
HashMap map = gson.fromJson(json1, HashMap.class);
HashMap map2 = gson.fromJson(json2, HashMap.class);
System.out.println(map);
System.out.println(map2);
System.out.println(map.get("amount").getClass());
System.out.println(map2.get("amount").getClass());
I get as output:
{amount=[1, 2], title=[1, 2]}
{amount=, title=}
class java.util.ArrayList
class java.lang.String
If I understood you correctly I think it suits you 100%
UPDATE
Since you are trying to deserialize your JSON string directly to a Data object, if you want to keep doing that direct deserialization you have to use a custom deserialization mechanism