将JSON反序列化为未知类型的集合 [英] Deserialize JSON to Collection of Unknown Types

查看:108
本文介绍了将JSON反序列化为未知类型的集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



谢谢。

解决方案


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


是, 有。如果不关心反序列化为特定Java类型的JSON结构只是一个包含键值对的对象,其中所有值都是JSON基元,那么结构可以简单地反序列化为<$ c $请注意, Map< String,Object> $ c>不会工作,因为它没有提供足够的Gson反序列化的类型信息。 Gson会为每个值创建简单的 Object 实例 - 而不是 String Integer 实例,但只是简单的 Object 实例。 JSON中的实际值不会被反序列化。从表面上看,可以增强Gson为 JsonPrimitive 值创建更多类型特定的实例。例如,因为可以通过调用来确定 JsonPrimitive 是否为 Boolean > isBoolean(),那么人们可能希望Gson会构造一个布尔,但它不会--Gson只是创建一个空的,可能-useless 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();
类型mapOfStringObjectType = new TypeToken< Map< String,String>>(){} .getType();
Map< String,String> map = gson.fromJson(new FileReader(input.json),mapOfStringObjectType);
System.out.println(map);




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



如果 Map type改为 HashMap< String,Object> ,则输出变为 {3 = java。 lang.Object@10b61fd1,one=java.lang.Object@24e2dae9,too=java.lang.Object@299209ea} ,这当然可能没用。



如果由于某种原因, HashMap< String,Object> 类型必须被反序列化为,则自定义反序列化处理将是如果JSON结构不是一组简单的键值对,其中的值都是JSON基元,但包含复杂类型的值,如JSON对象,即使将所有值转换为 Strings 也是可以接受的,那么也需要实现自定义的反序列化处理。



不要hes直接转到 Gson问题列表并提交增强请求用于将JSON原始反序列化改进为适当特定的Java Object 类型,或者具有简单的机制来转换任何值 - 包括像对象和数组这样的复杂JSON类型 - 在Map中转换为 String ,这样上面描述的自定义反序列化处理就没有必要。


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.

解决方案

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.

这篇关于将JSON反序列化为未知类型的集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆