【问题标题】:Deserialize JSON to Collection of Unknown Types将 JSON 反序列化为未知类型的集合
【发布时间】:2011-04-18 01:13:06
【问题描述】:

我正在用 Java 编写一个程序,通过调用一些方法向外部 API 发出请求。这些方法中的每一个都返回不同的 JSON 结构,它还取决于传递的参数。我的问题是,是否有某种方法可以使用 Gson 反序列化响应字符串,而不必为每种方法编写不同的类。

如果不是 Gson,我可以使用其他哪个库?

谢谢。

【问题讨论】:

    标签: java json gson


    【解决方案1】:

    我的问题是,是否有某种方法可以使用 Gson 反序列化响应字符串,而不必为每种方法编写不同的类。

    是的,有。如果您不想反序列化为特定 Java 类型的 JSON 结构只是一个包含键值对的对象,其中所有值都是 JSON 基元,那么该结构可以简单地反序列化为 Map<String, String>

    请注意,Map<String, Object> 不起作用,因为它没有为 Gson 提供足够的类型信息来反序列化。 Gson 只会为每个值创建普通的 Object 实例——不是 StringInteger 实例,而只是普通的 Object 实例。 JSON 中的实际值不会被反序列化。从表面上看,可以增强 Gson 以为JsonPrimitive 值创建更多特定于类型的实例似乎是合理的。例如,既然可以通过调用isBoolean() 来确定@​​987654332@ 是否是Boolean,那么人们可能希望Gson 只构造一个Boolean,但它没有——Gson 只是创建一个空的而且可能没用的Object

    这里有一个例子来说明这一点。

    input.json 内容:

    {
      "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);
      }
    }
    

    这个例子的输出是{3=false, one=won, too=22}

    如果示例中的Map类型按照另一个答案的建议改为HashMap&lt;String, Object&gt;,那么输出就变成{3=java.lang.Object@10b61fd1, one=java.lang.Object@24e2dae9, too=java.lang.Object@299209ea},这当然可能没用了。

    如果出于某种原因必须将HashMap&lt;String, Object&gt; 类型反序列化为,则需要自定义反序列化处理。

    如果 JSON 结构不是一组简单的键值对,其中的值都是 JSON 基元,但包含复杂类型的值,例如 JSON 对象,即使将所有值转换为 @987654344 也是可以接受的@,那么还需要实现自定义的反序列化处理。

    不要犹豫,前往 the Gson Issues List 并提交改进请求以改进 JSON 原语反序列化到适当特定的 Java Object 类型,或者拥有一个简单的机制来转换任何值 - 包括复杂的 JSON 类型比如对象和数组——在一个映射到String中,这样就不需要如上所述的自定义反序列化处理。

    【讨论】:

    • Gson 问题 325 解决了对 Map 的简单反序列化。请不要犹豫,在code.google.com/p/google-gson/issues/detail?id=325 投票支持它的实施
    • 请注意,Jackson (jackson.codehaus.org) 可以将上面的示例 JSON 反序列化为 Map 无需自定义处理,而 JSON-lib (json-lib.sourceforge.net) 可以类似地反序列化为 Map ( Map map = JSONObject.fromObject(json);).
    • 注意,我之前对这个主题所做的评论是针对 Gson 的早期版本。随着 Gson 问题 325 的实现,现在可以反序列化为 Map。我不确定,因为我还没有尝试这样做。
    【解决方案2】:

    如果你想使用 gson,你必须编写不同的类来代表不同方法的响应。如果响应是简单的键值对,那么您可以将响应转换为 HashMap&lt;String,Object&gt;,它将充当“通用”类以满足您用例中所有类型的响应。

    【讨论】:

    • 请注意 HashMap 没有包含足够的类型信息供 Gson 反序列化到。 Gson 只会为 Map 值创建普通的旧 Object 实例——不是来自 Object 的子类,如 String 或 Integer,而只是 Objects。我将在这个问题的答案中发布更多详细信息。
    • 注意,我之前对这个主题的评论是针对之前版本的 Gson。随着 Gson 问题 325 的实现,现在可以反序列化为 Map。我不确定,因为我还没有尝试这样做。
    猜你喜欢
    • 1970-01-01
    • 2016-11-01
    • 2015-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多