16

I have the following JSON snippets:

{ "randomlygeneratedKeyname0" : "some-value",
  "randomlygeneratedKeyname1": {
       "randomlygeneratedKeyname2" : {
           "randomlygeneratedKeyname3": "some-value",
           "randomlygeneratedKeyname4": "some-value"
       },
       "randomlygeneratedKeyname5": {
           "randomlygeneratedKeyname6": "some-value",
           "randomlygeneratedKeyname7": "some-value"
       }
   }
}

Notes that I don't know the name of randomlygeneratedKeyname and their naming convention is inconsistent so I could not create my corresponding Java field/variable names.

How do I (de)serialize it in GSON?

Thanks in advance for your help.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
pion
  • 3,593
  • 6
  • 29
  • 41

2 Answers2

26

I'm pleased to report that with GSON 2.0 supports default maps and lists without effort. Deserialize like this:

Object o = new Gson().fromJson(json, Object.class);

The result will be a Map with String keys and either String or Map values.

Serialize that map back to JSON like this:

String json = new Gson().toJson(o);

We hope to release GSON 2.0 in October 2012. You can get it early from GSON SVN.

Jesse Wilson
  • 39,078
  • 8
  • 121
  • 128
12

Code dump solution:

import java.io.FileReader;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.reflect.TypeToken;

public class Foo
{
  public static void main(String[] args) throws Exception
  {
    Type mapStringObjectType = new TypeToken<Map<String, Object>>() {}.getType();

    GsonBuilder gsonBuilder = new GsonBuilder();
    gsonBuilder.registerTypeAdapter(mapStringObjectType, new RandomMapKeysAdapter());
    Gson gson = gsonBuilder.create();

    Map<String, Object> map = gson.fromJson(new FileReader("input.json"), mapStringObjectType);
    System.out.println(map);
  }
}

class RandomMapKeysAdapter implements JsonDeserializer<Map<String, Object>>
{
  @Override
  public Map<String, Object> deserialize(JsonElement json, Type unused, JsonDeserializationContext context)
      throws JsonParseException
  {
    // if not handling primitives, nulls and arrays, then just 
    if (!json.isJsonObject()) throw new JsonParseException("some meaningful message");

    Map<String, Object> result = new HashMap<String, Object> ();
    JsonObject jsonObject = json.getAsJsonObject();
    for (Entry<String, JsonElement> entry : jsonObject.entrySet())
    {
      String key = entry.getKey();
      JsonElement element = entry.getValue();
      if (element.isJsonPrimitive())
      {
        result.put(key, element.getAsString());
      }
      else if (element.isJsonObject())
      {
        result.put(key, context.deserialize(element, unused));
      }
      // if not handling nulls and arrays
      else
      {
        throw new JsonParseException("some meaningful message");
      }
    }
    return result;
  }
}
Programmer Bruce
  • 64,977
  • 7
  • 99
  • 97
  • 2
    I forgot to mention, this mess is just one line with Jackson. Map map = new ObjectMapper().readValue(new File("input.json"), Map.class); – Programmer Bruce Jun 24 '11 at 02:18
  • I just looked at http://jackson.codehaus.org/ and http://wiki.fasterxml.com/JacksonInFiveMinutes. It seems that it is easier than GSON. Maybe I'll switch to it. – pion Jun 24 '11 at 02:45
  • Jackson is very easy to use. I'm finding it to be as easy as Gson, while offering more configuration options, doing things that Gson does not do, and doing them faster. – Programmer Bruce Jun 24 '11 at 03:33
  • Being new on both Gson and Jackson, Jackson's documentation seems to be more matured. – pion Jun 24 '11 at 13:56