Reputation: 1574
I'm writting a program in Java that makes requests to an external API by calling some methods. Each of these methods returns a diferent JSON structure and it also depends on the passed parameters. My question is if there's some way to deserialize the response string using Gson without having to write a different class for each method.
If not Gson, which other library could I use?
Thank you.
Upvotes: 1
Views: 8532
Reputation: 66963
My question is if there's some way to deserialize the response string using Gson without having to write a different class for each method.
Yes, there is. If the JSON structure that you don't care to deserialize into a specific Java type is just an object that contains key-value pairs, where all of the values are JSON primitives, then the structure can be simply deserialized into a Map<String, String>
.
Note that a Map<String, Object>
would not work as it does not provide enough type information for Gson to deserialize into. Gson would just create plain Object
instances for each value -- not String
or Integer
instances, but just plain Object
instances. The actual values in the JSON would not be deserialized. On the surface it seems reasonable that Gson could be enhanced to create more type-specific instances for JsonPrimitive
values. For example, since it's possible to determine whether a JsonPrimitive
is a Boolean
, with a call to isBoolean()
, then one might hope Gson would just construct a Boolean
, but it doesn't -- Gson just creates an empty and probably-useless Object
.
Here's an example that demonstrates this point.
input.json Contents:
{
"one":"won",
"too":22,
"3":false
}
Foo.java:
import java.io.FileReader;
import java.lang.reflect.Type;
import java.util.Map;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class Foo
{
public static void main(String[] args) throws Exception
{
Gson gson = new Gson();
Type mapOfStringObjectType = new TypeToken<Map<String, String>>() {}.getType();
Map<String, String> map = gson.fromJson(new FileReader("input.json"), mapOfStringObjectType);
System.out.println(map);
}
}
The output of this example is {3=false, one=won, too=22}
.
If the Map
type in the example is changed to HashMap<String, Object>
as recommended in another answer, then the output becomes {3=java.lang.Object@10b61fd1, one=java.lang.Object@24e2dae9, too=java.lang.Object@299209ea}
, which is of course probably useless.
If for some reason a type of HashMap<String, Object>
must be deserialized to, then custom deserialization processing would be necessary.
If the JSON structure is not a simple set of key-value pairs, where the values are all JSON primitives, but include values that are complex types like JSON objects, even if it's acceptable to transform all of the values into Strings
, then it would also be necessary to implement custom deserialization processing.
Don't hesitate to head on over to the Gson Issues List and submit an enhancement request for improved JSON primitive deserialization to appropriately specific Java Object
types, or to have a simple mechanism to transform any value -- including complex JSON types like objects and arrays -- in a Map into a String
, such that custom deserialization processing as described above wouldn't be necessary.
Upvotes: 4
Reputation: 7779
You have to write different class which would represent the responses from different methods if you want to use gson. If the response is simple key-value, then you can convert the response into a HashMap<String,Object>
which will act as a 'generic' class to satisfy all type of responses in your use case.
Upvotes: 1