Лучший способ построить REST api для поиска с использованием операндов JSON

#java #json #spring #rest #spring-mvc

#java #json #spring #rest #spring-mvc

Вопрос:

Я пытаюсь создать REST api для своего приложения. Основы выполнены. Но теперь мне нужна помощь для поиска с различными параметрами и их операндами.

Допустим, у меня есть строка JSON, подобная этой:

 {"v00Datvon":"09-07-2014","v00Datbis":"09-07-2014","v00Saicode":{"saiCode":"SO02"}}
  

Это значения моего доменного объекта «contract».

Для поиска в части пользовательского интерфейса вы можете выбрать для двух дат операнд (больший, меньший или равный)

Все параметры (без операндов) отправляются при вызове GET и Ajax.

Контроллер Spring MVC выглядит следующим образом:

     @RequestMapping(value = "/", method = RequestMethod.GET, headers = "Accept=application/json")
    public ResponseEntity<String> getContractsFromSearch(@RequestParam String allRequestParams, ModelMap model){
    //some stuff
    }
  

Я ищу техническую информацию, как добавить операнды в строку JSON и контроллер чистым и хорошим способом. Я не хочу взламывать какой-то плохой код.
Если вам нужно больше информации, пожалуйста, оставьте комментарий.
Спасибо!

Обновление 1.

ПОЛУЧИТЬ запрос:

 allRequestParams={"v00Datvon":"09-07-2014","v00Datbis":"09-07-2014","v00Saicode":{"saiCode":"SO02"}}
  

Обновление 2.

     {
  "dateFrom": {
    "dateFrom": "someDate",
    "operand": "less"
  },
  "dateTo": {
    "dateTo": "someDate",
    "operand": "greater"
  },
  "season": {
    "season": "someSeason",
    "operand": "equals"
  }
}
  

Обновление 3
Десериализация:

 public static Contract fromJsonToContract(String json) {
    return new JSONDeserializer<Contract>().use(Calendar.class, new CalendarTransformer("dd-MM-yyyy HH:mm")).use(null, Contract.class).deserialize(json);
}
  

Комментарии:

1. Не могли бы вы, пожалуйста, показать нам пример GET запроса? Как выглядят параметры в URL-адресе?

2. На данный момент я не добавляю операнды в параметры. Я не уверен, что смогу сделать это хорошим способом.

3. Есть другие предложения?

4. Используйте кодировку ISO-8601 для дат. GET URL выглядит как find.

5. GET URL работает нормально. Проблема не в этом. Мне нужна помощь, чтобы добавить параметры операндов к этому URL. Чистым и хорошим способом. Может быть, будут какие-то стандарты? Спасибо

Ответ №1:

Прежде всего, в соответствии с вашим контроллером, как вы передаете Map как RequestParam, это невозможно, попробуйте это

  @RequestMapping(value = "/", method = RequestMethod.GET, headers = "Accept=application/json")
    public ResponseEntity<String> getContractsFromSearch(HttpServletRequest request, Object> allRequestParams, ModelMap model){
Enumeration paramNames = request.getParameterNames();
while(paramNames.hasMoreElements())
{
      String paramName =
(String)paramNames.nextElement();
      out.print(paramName);
}
    //some stuff
    }
  

Комментарии:

1. Карта работает нормально. Вывод карты выглядит следующим образом: {dateFrom=02-07-2014, dateTo=02-07-2014, season=SO03} Но есть ли у вас какие-либо предложения по добавлению операндов в список параметров вашего решения?

2. Есть другие предложения?

3. перед переходом к вашему контроллеру установите некоторую логику фильтрации, к которой вы можете легко добавлять операнды

4. ОК. Но как должен выглядеть json? Как в обновлении 2, о котором идет речь? Или есть какой-то стандарт?

5. да, вы можете предпочесть update2 json, который выглядит осмысленно

Ответ №2:

Я думаю, что ваш JSON слишком подробный: у вас есть запись с именем «DateFrom», в которой есть запись с именем «DateFrom», постарайтесь, чтобы она была простой и «плоской». Как насчет этой опции?:

  {
  "dateFrom": "someDate",
  "operandFrom": "less",

  "dateTo": "someDate",
  "operandTo": "greater",

  "season": "someSeason",
  "operandSeason": "equals"

}
  

Я знаю, что группировать данные по семантике заманчиво, но в запросе GET вы должны продумать наилучший способ обработки параметров.Данные могут быть легко преобразованы в:

 dateFrom=someDateamp;operandFrom=lessamp;dateTo=someDateamp;operandTo=greateramp;season=someSeasonamp;operandSeason=equals
  

или просто отправьте один параметр с JSON в качестве значения:

 q={"dateFrom": "someDate","operandFrom":"less","dateTo":"someDate","operandTo":"greater","season":"someSeason","operandSeason":"equals"}
  

Но тогда вам нужно было бы проанализировать его в вашем контроллере.