使用GSON处理随机生成和不一致的JSON字段/键名

17

我有以下JSON片段:

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

注意,我不知道randomlygeneratedKeyname的名称,它们的命名约定不一致,因此我无法创建相应的Java字段/变量名称。

我该如何在GSON中进行(反)序列化?

提前感谢您的帮助。


你希望生成什么样的数据结构呢?一个 Map<String, Map<String, Map<String, ...>>> 吗? - Matt Ball
我对任何数据结构都很开放。Map<>可以使用。如何在GSON中实现? - pion
1
如果针对325问题的解决方案得以实施,这将变得很容易。http://code.google.com/p/google-gson/issues/detail?id=325 - Programmer Bruce
2个回答

26

很高兴地报告,使用 GSON 2.0 可轻松支持默认的 maps 和 lists。像这样反序列化:

Object o = new Gson().fromJson(json, Object.class);
结果将是一个使用String键和StringMap值的Map。将该映射序列化回JSON,如下所示:
String json = new Gson().toJson(o);

我们希望在2012年10月发布GSON 2.0版本。您可以从GSON SVN提前获取它。


12

代码转储解决方案:

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;
  }
}

2
我忘了提到,这个混乱的代码只是使用Jackson的一行。Map map = new ObjectMapper().readValue(new File("input.json"), Map.class); - Programmer Bruce
我刚刚查看了http://jackson.codehaus.org/和http://wiki.fasterxml.com/JacksonInFiveMinutes。它似乎比GSON更容易使用。也许我会转换到它。 - pion
Jackson非常容易使用。我发现它和Gson一样容易,同时提供更多的配置选项,做一些Gson不能做的事情,并且速度更快。 - Programmer Bruce
作为对Gson和Jackson都不熟悉的新手,Jackson的文档似乎更加成熟。 - pion

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接