将 JSON 字符串转换为 JAVA 中的通用对象(使用 GSON)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17712052/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert JSON String to generic object in JAVA (with GSON)
提问by Yannis
I have an Api that returns JSON. The response is in some format that can fit into an object called ApiResult and contains a Context <T>
and an int Code.
我有一个返回 JSON 的 Api。响应采用某种格式,可以放入名为 ApiResult 的对象中,并包含一个Context <T>
和一个 int 代码。
ApiResult is declared in a generic way, e.g. ApiResult<SomeObject>
ApiResult 以通用方式声明,例如 ApiResult<SomeObject>
I would like to know how to get GSON to convert the incoming JSON String to ApiResult<T>
我想知道如何让 GSON 将传入的 JSON 字符串转换为 ApiResult<T>
So far I have:
到目前为止,我有:
Type apiResultType = new TypeToken<ApiResult<T>>() { }.getType();
ApiResult<T> result = gson.fromJson(json, apiResultType);
But this still returns converts the Context to a LinkedHashMap instead (which I assume its what GSON falls back to)
但这仍然返回将 Context 转换为 LinkedHashMap (我假设它是 GSON 回退到的)
回答by Chris Kessel
You have to know what T is going to be. The incoming JSON is fundamentally just text. GSON has no idea what object you want it to become. If there's something in that JSON that you can clue off of to create your T instance, you can do something like this:
你必须知道 T 会是什么。传入的 JSON 基本上只是文本。GSON 不知道你想让它变成什么对象。如果该 JSON 中有一些内容可以帮助您创建 T 实例,则可以执行以下操作:
public static class MyJsonAdapter<X> implements JsonDeserializer<ApiResult<X>>
{
public ApiResult<X> deserialize( JsonElement jsonElement, Type type, JsonDeserializationContext context )
throws JsonParseException
{
String className = jsonElement.getAsJsonObject().get( "_class" ).getAsString();
try
{
X myThing = context.deserialize( jsonElement, Class.forName( className ) );
return new ApiResult<>(myThing);
}
catch ( ClassNotFoundException e )
{
throw new RuntimeException( e );
}
}
}
I'm using a field "_class" to decide what my X needs to be and instantiating it via reflection (similar to PomPom's example). You probably don't have such an obvious field, but there has to be some way for you to look at the JsonElement and decide based on what's itn it what type of X it should be.
我正在使用字段“_class”来决定我的 X 需要是什么并通过反射实例化它(类似于 PomPom 的示例)。您可能没有这么明显的字段,但必须有某种方式让您查看 JsonElement 并根据它的内容来决定它应该是什么类型的 X。
This code is a hacked version of something similar I did with GSON a while back, see line 184+ at: https://github.com/chriskessel/MyHex/blob/master/src/kessel/hex/domain/GameItem.java
这段代码是我不久前用 GSON 做的类似事情的黑客版本,请参阅第 184+ 行:https: //github.com/chriskessel/MyHex/blob/master/src/kessel/hex/domain/GameItem.java
回答by CodeShadow
My solution is using org.json and Hymanson
我的解决方案是使用 org.json 和 Hymanson
Below are the methods to wrap a json object into an array, to convert an object to into a list and to convert json string to a type.
以下是将 json 对象包装成数组、将对象转换为列表以及将 json 字符串转换为类型的方法。
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
public <T> List<T> parseJsonObjectsToList(JSONObject parentJson, String key, Class<T> clazz) throws IOException {
Object childObject = parentJson.get(key);
if(childObject == null) {
return null;
}
if(childObject instanceof JSONArray) {
JSONArray jsonArray = parentJson.getJSONArray(key);
return getList(jsonArray.toString(), clazz);
}
JSONObject jsonObject = parentJson.getJSONObject(key);
List<T> jsonList = new ArrayList<>();
jsonList.add(getObject(jsonObject.toString(), clazz));
return jsonList;
}
public <T> List<T> getList(String jsonStr, Class clazz) throws IOException {
ObjectMapper objectMapper = OBJECT_MAPPER;
TypeFactory typeFactory = objectMapper.getTypeFactory();
return objectMapper.readValue(jsonStr, typeFactory.constructCollectionType(List.class, clazz));
}
public <T> T getObject(String jsonStr, Class<T> clazz) throws IOException {
ObjectMapper objectMapper = OBJECT_MAPPER;
return objectMapper.readValue(jsonStr, clazz);
}
// To call
parseJsonObjectsToList(creditReport, JSON_KEY, <YOU_CLASS>.class);
回答by PomPom
You have to provide Gson the type of T
. As gson doesn't know what adapter should be applied, it simply return a data structure.
您必须为 Gson 提供T
. 由于 gson 不知道应该应用什么适配器,它只是返回一个数据结构。
Your have to provide the generic, like :
您必须提供泛型,例如:
Type apiResultType = new TypeToken<ApiResult<String>>() { }.getType();
If type of T is only known at runtime, I use something tricky :
如果 T 的类型仅在运行时已知,我会使用一些棘手的东西:
static TypeToken<?> getGenToken(final Class<?> raw, final Class<?> gen) throws Exception {
Constructor<ParameterizedTypeImpl> constr = ParameterizedTypeImpl.class.getDeclaredConstructor(Class.class, Type[].class, Type.class);
constr.setAccessible(true);
ParameterizedTypeImpl paramType = constr.newInstance(raw, new Type[] { gen }, null);
return TypeToken.get(paramType);
}
Your call would be (but replacing String.class
with a variable) :
您的电话将是(但替换String.class
为变量):
Type apiResultType = getGenToken(ApiResult.class, String.class);
回答by Rodion Altshuler
I use HymansonJson library, quite similar to GSon. It's possible to convert json string to some generic type object this way:
我使用 HymansonJson 库,与 GSon 非常相似。可以通过这种方式将 json 字符串转换为一些通用类型对象:
String data = getJsonString();
ObjectMapper mapper = new ObjectMapper();
List<AndroidPackage> packages = mapper.readValue(data, List.class);
Maybe this is correct way with GSON in your case:
在您的情况下,这可能是 GSON 的正确方法:
ApiResult<T> result = gson.fromJson(json, ApiResult.class);