将JSON字符串转换为JAVA中的通用对象(使用GSON)

时间:2013-07-17 23:33:08

标签: java gson

我有一个返回JSON的Api。响应采用某种格式,可以放入名为ApiResult的对象中,并包含Context <T>和int代码。

ApiResult以通用方式声明,例如ApiResult<SomeObject>

我想知道如何让GSON将传入的JSON字符串转换为ApiResult<T>

到目前为止,我有:

Type apiResultType = new TypeToken<ApiResult<T>>() { }.getType();
ApiResult<T> result = gson.fromJson(json, apiResultType);

但是这仍然会返回将Context转换为LinkedHashMap(我假设它是GSON的回归)

4 个答案:

答案 0 :(得分:5)

你必须知道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 );
      }
    }
}

我正在使用字段“_class”来决定我的X需要什么,并通过反射实例化它(类似于PomPom的例子)。你可能没有这么明显的领域,但是你必须有一些方法来查看JsonElement,并根据它应该是什么类型的X来决定。

此代码是类似我之前与GSON类似的黑客版本,请参阅第184行:https://github.com/chriskessel/MyHex/blob/master/src/kessel/hex/domain/GameItem.java

答案 1 :(得分:1)

你必须为Gson提供T的类型。由于gson不知道应该应用什么适配器,它只是返回一个数据结构。

您必须提供通用,例如:

Type apiResultType = new TypeToken<ApiResult<String>>() { }.getType();

如果只在运行时知道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);
  }

您的电话会是(但用变量替换String.class):

Type apiResultType = getGenToken(ApiResult.class, String.class);

答案 2 :(得分:1)

我的解决方案是使用org.json和Jackson

以下是将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);

答案 3 :(得分:0)

我使用JacksonJson库,与GSon非常相似。可以通过这种方式将json字符串转换为某种泛型类型对象:

String data = getJsonString();
ObjectMapper mapper = new ObjectMapper();
List<AndroidPackage> packages = mapper.readValue(data, List.class);

在您的情况下,使用GSON可能这是正确的方法:

ApiResult<T> result = gson.fromJson(json, ApiResult.class);