0x77D
0x77D

Reputation: 1574

Deserialize JSON to Collection of Unknown Types

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

Answers (2)

Programmer Bruce
Programmer Bruce

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

lobster1234
lobster1234

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

Related Questions