Преобразовать строку Json в объект, используя Gson для динамических типов классов - PullRequest
0 голосов
/ 21 марта 2019

Я пытаюсь написать маршрутизатор запросов, который получит запрос HTTP POST и на основе URL-адреса запроса преобразует Json в теле запроса в соответствующий класс Java.

У меня есть класс Route для инкапсуляции типов классов URL, обработчиков, запросов и ответов. Ниже приведена голая версия класса Route без каких-либо методов получения и установки.

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 голосов
/ 21 марта 2019

Ошибка, препятствующая компиляции Java-проекта, обусловлена ​​безопасностью типов:

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

Метод fromJson является универсальным методом , что означает, что он вернет объекттип класса, который передается в качестве параметра.Однако в этом случае тип класса 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
    }
}
0 голосов
/ 21 марта 2019

вы можете использовать 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...