Статьи

JSON, POJO и класс Groovy HTTPBuilder

Хотя в предыдущих статьях рассматривалось использование RESTClient , эта статья будет посвящена его родительскому классу HTTPBuilder, а также кратко коснется класса JSONBuilder . Этот пост будет посвящен построению и анализу JSON, преобразованию JSON в POJO и из него, добавлению заголовков аутентификации и обработке успешных и неудачных ответов.

Класс HTTPBuilder предоставляет API для создания HTTP-запросов и анализа ответов и основывается на классе Apache AbstractHttpClient . Класс HTTPBuilder может быть создан с помощью URI, который будет использоваться по умолчанию для всех методов запроса. Тип контента по умолчанию также может быть предоставлен, но для этого примера это будет экземпляр по умолчаниюContentType.ANY .

Приведенный ниже метод принимает POJO AccountFilter, создает объект JSONBuilder и создает экземпляр HTTPBuilder с URI по умолчанию. Затем он делает запрос с указанием метода (POST) и contentType (JSON). Тело запроса будет преобразовано в строку формы в кодировке URL. Код также показывает, как можно установить заголовки, в этом случае X-Application и X-Authentication с использованием переменных экземпляра.


ПРИМЕЧАНИЕ: запрос извлекает данные, а не создает или обновляет данные, поэтому обычно это GET, но критерии могут быть сложными и вложенными, и, следовательно, его необходимо отправлять в виде JSON в теле запроса, следовательно, с использованием POST. (В интернете целая дискуссия о GET-запросах, содержащих тело запроса.)





Set<Customer> listCustomers(AccountFilter accountFilter) {
 
    def resultList = new ArrayList<Customer>()
    def builder = new JsonBuilder(accountFilter)
    def http = new HTTPBuilder( 'https://beta-api.city81.com/json-rpc' )
 
  
    // POST request
    http.request (POST, JSON){req->
        body = [
            "jsonrpc" : "2.0",
            "method" : "Bank/v1.0/listCustomers",
            "params" : builder.toString(),
            "id" : 1
        ]
 
        headers.'X-Application' = this.applicationKey
        headers.'X-Authentication' = this.sessionToken
 
        // success response handler
        response.success = { resp, json ->
            json.result.each {
                resultList.add(new Customer(
                    it.customer.id, it.customer.name))
            }
        }
 
        // failure response handler
        response.failure = { resp ->
            println "Unexpected error: ${resp.statusLine.statusCode}"
            println ${resp.statusLine.reasonPhrase}
        }
    }
 
    return resultList
}


Обработчик успешного ответа будет перебирать набор результатов JSON и создавать объекты Customer, добавляя их в коллекцию. Обработчик ответа на ошибку выведет код состояния и фразу причины сбоя запроса POST.

Как упоминалось выше, код использует JSONBuilder, чтобы превратить POJO в JSON. Для фильтра POJO с установленным полем accountIds JSON будет выглядеть следующим образом:

«params»: {«filter»: {«accountIds»: [1]}}

В этом есть недостаток, заключающийся в том, что если атрибут фильтра MarketFilter не установлен, то тег Filter не будет присутствовать в JSON. Если служба, к которой вы делаете POST, требует, чтобы это было обязательным (хотя и пустым), тогда строка req body params будет выглядеть так:

«params»: [filter: [:]],

который будет генерировать JSON:

«param»: {«filter»: {}}

Этот пост охватывает только небольшую часть HTTPBuilder и один из нескольких способов POST-запроса, генерации JSON и анализа его ответа, многие из которых были упрощены с помощью RESTClient учебный класс.




POJOS используется в приведенном выше примере:

public class Customer {
 
    private String id;
    private String name;
 
    public Customer(String id, String name) {
        this.id = id;
        this.name = name;
    }
    
    // ... getters and setters
 }
 
 
 public class AccountFilter {
 
    private Filter filter;
   
 
    public AccountFilter(Filter filter) {
        this.filter = filter;
    }
    
    // ... getters and setters
 }
 
 
public class Filter {
   
 
    private Set<String> accountIds;
 
    // ... getters and setters
}