使用Gson将Json字符串转换为对象以获取动态类类型

时间:2019-03-21 05:13:42

标签: java gson

我正在尝试编写一个请求路由器,该路由器将接收HTTP POST请求,并基于请求的URL,将请求正文中的Json转换为相应的Java类。

我有一个Route类,用于封装路由url,处理程序,请求和响应类类型。下面是Route类的基本版本,其中没有任何getter和setter。

public class Route {
  public String url;
  public Class requestClass;
  public Class responseClass;

  public Route(String url, Class requestClass, Class responseClass) {
    this.url = url;
    this.requestClass = requestClass;
    this.responseClass = responseClass;
  }
}

我为在路由器中注册的所有路由保留一个ImmutableList。

ImmutableList.<Route>builder()
          .add(
              new Route(
                  "/getemployeebyfilters",
                  GetEmployeeByFiltersRequest.class,
                  GetEmployeeByFiltersResponse.class,
                  new GetEmployeeByFiltersHandler()))
          .add(
              new Route(
                  "/getcompanybyfilters",
                  GetCompanyByFiltersRequest.class,
                  GetCompanyByFiltersResponse.class,
                  new GetCompanyByFiltersHandler()))
          .build();

在接收到新请求后,我读取了请求的Json主体,并尝试将其解析为相应类的对象。

import com.google.gson.Gson;

Gson gson = new Gson();

for (Route route : routes) {
  if (route.url.equals(requestPath)) {
    GetEmployeeByFiltersRequest request = gson.fromJson(body, route.requestClass);
  }
}

这使编译器抛出以下错误/警告:

./Router.java:61: warning: [unchecked] unchecked method invocation: method fromJson in class Gson is applied to given types
        GetEmployeeByFiltersRequest request = gson.fromJson(body, route.requestClass);
                                                           ^
  required: String,Class<T>
  found: String,Class
  where T is a type-variable:
    T extends Object declared in method <T>fromJson(String,Class<T>)
./Router.java:61: warning: [unchecked] unchecked conversion
        GetEmployeeByFiltersRequest request = gson.fromJson(body, route.requestClass);
                                                                       ^
  required: Class<T>
  found:    Class
  where T is a type-variable:
    T extends Object declared in method <T>fromJson(String,Class<T>)
./Router.java:61: error: incompatible types: Object cannot be converted to GetEmployeeByFiltersRequest
        GetEmployeeByFiltersRequest request = gson.fromJson(body, route.requestClass);
                                                           ^
1 error
2 warnings

如果有人能指出我正确的方向,我将不胜感激。我可以灵活地更改Route类。

谢谢

2 个答案:

答案 0 :(得分:0)

您可以使用com.fasterxml.jackson.databind.ObjectMapper进行转换

示例代码

public static  <T> T convertJsonToObject(String jsonString, Class<T> clazz)  {
    T object = null;


        ObjectMapper objectMapper = new ObjectMapper();
        object = objectMapper.reader().forType(clazz).readValue(jsonString);

    return object;
}

答案 1 :(得分:0)

阻止编译Java项目的错误是由于类型安全引起的:

./Router.java:61: error: incompatible types: Object cannot be converted to GetEmployeeByFiltersRequest
        GetEmployeeByFiltersRequest request = gson.fromJson(body, route.requestClass);

fromJson方法是Generic Method,这意味着它将返回类类型的对象,该对象作为参数传入。但是,在这种情况下,在编译时不知道route.requestClass的类类型(它可以是GetEmployeeByFiltersRequest类型或GetCompanyByFiltersRequest类型)。

在这种情况下,gson.fromJson无法保证它将返回类型为GetEmployeeByFiltersRequest的对象。实际上route.requestClass可以很容易地成为GetCompanyByFiltersRequest类型,这是Java为什么不编译它的反例。

将行更改为以下内容即可编译,但是我不建议将其作为设计模式:

Object request = gson.fromJson(body, route.requestClass);

现在,请求将是通用Object类型的,并且将失去所有类型的安全性。

我认为处理请求路由的一个更好的选择是使用类似于WebServlet的注释。

它允许您指定与HTTP端点相对应的类:

@WebServlet("/employees")
class Employees extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request,
        HttpServletResponse response)
        throws Exception {
        // do stuff for employees 
    }
}

@WebServlet("/companies")
class Companies extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request,
        HttpServletResponse response)
        throws Exception {
        // do stuff for companies
    }
}