2011-04-18 138 views
1

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

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

谢谢。

回答

4

我的问题是如果有一些方法来反序列化使用Gson的响应字符串,而无需为每种方法编写不同的类。

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

请注意,Map<String, Object>将无法​​正常工作,因为它不会为Gson反序列化提供足够的类型信息。 Gson只会为每个值创建普通的Object实例 - 而不是StringInteger实例,但只是简单的Object实例。 JSON中的实际值不会被反序列化。从表面上看,可以增强Gson为JsonPrimitive值创建更多类型特定的实例。例如,由于可以确定JsonPrimitive是否为Boolean,并调用isBoolean(),那么人们可能会希望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<String, Object>,如其他答案中的建议,则输出将变为{[email protected], [email protected], [email protected]},这当然可能是无用的。

如果由于某种原因某种类型的HashMap<String, Object>必须将反序列化为,则自定义的反序列化处理将是必要的。

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

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

+0

Gson问题325解决了简单的反序列化为Map 。请不要犹豫,通过http://code.google.com/p/google-gson/issues/detail?id=325 – 2011-06-13 06:27:54

+0

投票支持其实施。请注意,杰克逊(http://jackson.codehaus.org)可以将上面的示例JSON反序列化为没有自定义处理的Map ,并且JSON-lib(http://json-lib.sourceforge.net)可以类似地反序列化为Map(Map map = JSONObject.fromObject(json) )。 – 2011-06-13 06:32:12

+0

请注意,我之前对此主题的评论是针对Gson的以前版本的。随着Gson问题325的实现,它现在可能只是反序列化为Map 。我不确定,因为我还没有尝试这样做。 – 2013-01-10 19:53:51

1

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

+0

请注意,HashMap 不包含Gson反序列化到的足够的类型信息。 Gson只会为Map值创建普通的旧Object对象 - 而不是像String或Integer这样的Object的子类,而只是Object。我会在回答这个问题时发布更多细节。 – 2011-06-10 09:05:46

+1

请注意,我之前对此主题的评论是针对Gson的以前版本的。随着Gson问题325的实现,它现在可能只是反序列化为Map 。我不确定,因为我还没有尝试这样做。 – 2013-01-10 19:53:32