class com.google.gson.internal.LinkedTreeMap cannot be cast to class [duplicate] - java

I have a domain object Foo, and I want to parse some JSON such as
[
{"prop": "val"},
{"prop": "val2"},
]
I want to get a List<Foo>. Something like this
List<Foo> foos = new Gson().fromJson(json, /*what goes here ?*/);

You need to use a TypeToken to correctly express the type. Class is not sufficient in this case, because of the interaction with the generic type.
Type listType = new TypeToken<List<Foo>>(){}.getType();
List<Foo> projects = (List<Foo>) gson.fromJson(response, listType);

Related

How to decode generic data in Jackson?

How can I do like this:
Test<String> data = OBJECT_MAPPER.decodeValue("sss", Test<String>.class);
When I call this operation I get an error. I need decode generic class.
Thanks for the help.
You can use TypeReference. Test<String>.class is not possible in Java.
TypeReference testStringType = new TypeReference<Test<String>>() { };
Object value = mapper.readValue(json, testStringType);
Also works:
JavaType javaType = mapper.getTypeFactory().constructParametricType(Test.class, String.class);
Test<String> value1 = mapper.readValue(json, javaType);
See also:
Jackson - Deserialize using generic class
Jackson - Deserialize Generic class variable

TypeToken usage mandatory?

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

Java/Android - Gson().fromJson() with Type is still giving an Unchecked cast Warning

I use the Gson().fromJson method to convert a JSON-String to a List of my Object (Products). I've heard I need to use a Type as a parameter in the fromJson to prevent getting an Unchecked cast Warning, but I'm still getting it..
Here is my code:
List<Product> p = null;
try{
// Convert JSON-string to a List of Product objects
Type listType = new TypeToken<List<Product>>(){}.getType();
p = (List<Product>)new Gson().fromJson(json, listType);
}
catch(JsonParseException ex){
ex.printStackTrace();
}
Why do I still get the Unchecked cast Warning [Object to List]?
Another option is to use ObjectMapper from Jackson API instead of Gson.
new ObjectMapper().readValue(json, new TypeReference<List<Product>>() {});
One reason for suggesting an alternative is because TypeToken is still declared as an unstable class.
I changed
List<Product> p = (List<Product>) new Gson().fromJson(json, listType);
to
List<Product> p = new Gson().fromJson(json, listType);
and now I don't have the warning anymore.

I can't return List<bean> from the Json? Java.lang.ClassCastException

There is json in my metod. I want json change to object bean. compiler warns and asks to remove generic.
This example does not work:
Gson gson = new Gson();
List<MyBean> myBean = gson.fromJson(
result.getBody(), List<myBean>.class);
So does run, but I can not get to the bean:
Gson gson = new Gson();
List<MyBean> myBean = gson.fromJson(
result.getBody(), List.class);
MyBean.get(0).getFirstName();
error java.lang.ClassCastException: com.google.gson.internal.StringMap cannot be cast to com.home.bean.MyBean
How do I solve this problem?
Try this:
Type myBeanListType = new TypeToken<ArrayList<MyBean>>() {}.getType();
List<MyBean> mappedList = new Gson().fromJson(result.getBody(), myBeanListType );
Your code would have to be changed to:
List<MyBean> myBean = gson.fromJson(result.getBody(), new TypeToken<List<MyBean>>() {}.getType());
Per the Gson user guide here, (under Serializing and Deserializing Generic Types section):
When you call toJson(obj), Gson calls obj.getClass() to get
information on the fields to serialize. Similarly, you can typically
pass MyClass.class object in the fromJson(json, MyClass.class) method.
This works fine if the object is a non-generic type. However, if the
object is of a generic type, then the Generic type information is lost
because of Java Type Erasure.
You can solve this problem by specifying the correct parameterized
type for your generic type. You can do this by using the TypeToken
class.
Hence, you would have to use TypeToken when dealing with generics.

Get element name with GSON

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...

Categories