Статьи

Объяснение привязки MOXy JSON на стороне клиента


Недавно я
писал о том, как использовать
привязку JSON EclipseLink JAXB (MOXy) для создания службы RESTful. В этой статье я покажу, как легко использовать преимущества JSON-связывания MOXy на стороне клиента.

URI

Этот пост будет посвящен следующему URI от сервиса, который мы объявили в
предыдущем посте
. Следующий звонок вернет список клиентов, которые живут в «Любом городе».

Клиентские API Java SE

В первом примере мы будем использовать стандартные API Java SE 6. Некоторые интересные вещи, чтобы отметить:

  • MOXy может непосредственно маршалировать (строка 35) и демаршалировать (строка 28) коллекции в / из массивов JSON без необходимости использования объекта-оболочки.
  • На MOXy нет зависимостей времени компиляции (это зависимость времени выполнения).
  • Свойство eclipselink.media-type используется для включения привязки JSON для демаршаллера (строка 25) и маршаллера (строка 33).
  • Свойство eclipselink.json.include-root используется для указания того, что аннотация @XmlRootElement должна игнорироваться в привязке JSON (строки 26 и 34).

package example;
 
import java.io.InputStream;
import java.net.*;
import java.util.List;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
import org.example.Customer;
 
public class JavaSEClient {
 
    private static final String MEDIA_TYPE = "application/json";
 
    public static void main(String[] args) throws Exception {
        String uri = "http://localhost:8080/CustomerService/rest/customers/findCustomersByCity/Any%20Town";
        URL url = new URL(uri);
        HttpURLConnection connection =
            (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setRequestProperty("Accept", MEDIA_TYPE);
 
        JAXBContext jc = JAXBContext.newInstance(Customer.class);
 
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        unmarshaller.setProperty("eclipselink.media-type", MEDIA_TYPE);
        unmarshaller.setProperty("eclipselink.json.include-root", false);
        InputStream xml = connection.getInputStream();
        List<Customer> customers = (List<Customer>) unmarshaller.unmarshal(new StreamSource(xml), Customer.class).getValue();
        connection.disconnect();
 
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setProperty("eclipselink.media-type", MEDIA_TYPE);
        marshaller.setProperty("eclipselink.json.include-root", false);
        marshaller.marshal(customers, System.out);
    }
 
}
Выходные данные

Ниже приведены результаты работы клиента Java SE. Для тех, кто мог использовать реализацию JAXB (
JSR-222 ) с чем-то вроде
Jettison для производства / потребления JSON, вот несколько интересных моментов , на которые следует обратить внимание:

  • MOXy отображает коллекции в виде массивов JSON.
  • MOXy правильно представляет числовые значения без кавычек (строка 26).
  • MOXy правильно окружает коллекции размера 1 квадратными скобками (строки 28 и 32).

[ {
   "address" : {
      "city" : "Any Town",
      "id" : 1,
      "street" : "1 A Street"
   },
   "firstName" : "Jane",
   "id" : 1,
   "lastName" : "Doe",
   "phoneNumbers" : [ {
      "id" : 2,
      "num" : "555-2222",
      "type" : "HOME"
   }, {
      "id" : 1,
      "num" : "555-1111",
      "type" : "WORK"
   } ]
}, {
   "address" : {
      "city" : "Any Town",
      "id" : 10,
      "street" : "456 Another Road"
   },
   "firstName" : "Sue",
   "id" : 10,
   "lastName" : "Jones",
   "phoneNumbers" : [ {
      "id" : 10,
      "num" : "555-3333",
      "type" : "WORK"
   } ]
} ]
Клиентские API Джерси

JAX-RS 2.0 (
JSR-339
) работает над стандартизацией клиентских API. С JAX-RS 1.0 многие реализации предоставляют свою собственную версию. Ниже приведен пример использования клиентских API, предоставленных
Jersey
. Обратите внимание, как мы можем использовать точно такой же
MessageBodyReader
/
Writer,
который мы использовали на стороне сервера (строка 14,
обозначьте MOXy как Ваш JSON-поставщик JAX-RS — Сторона сервера
). Я также указал LoggingFilter (строка 17), чтобы мы могли более внимательно посмотреть на сообщение.

package example;
 
import java.util.List;
import org.example.Customer;
import org.example.MOXyJSONProvider;
import com.sun.jersey.api.client.*;
import com.sun.jersey.api.client.config.*;
import com.sun.jersey.api.client.filter.LoggingFilter;
 
public class JerseyClient {
 
    public static void main(String[] args) {
        ClientConfig cc = new DefaultClientConfig();
        cc.getClasses().add(MOXyJSONProvider.class);
 
        Client client = Client.create(cc);
        client.addFilter(new LoggingFilter());
 
        WebResource resource = client.resource("http://localhost:8080/CustomerService/rest/customers");
        List<Customer> customers = resource.path("/findCustomersByCity/Any%20Town").accept("application/json").get(new GenericType<List<Customer>>(){});
 
        for(Customer customer : customers) {
            System.out.println(customer.getFirstName());
        }
    }
 
}

Выход

Ниже приведен результат запуска клиента Джерси.

14-Mar-2012 4:08:12 PM com.sun.jersey.api.client.filter.LoggingFilter log
INFO: 1 * Client out-bound request
1 > GET http://localhost:8080/CustomerService/rest/customers/findCustomersByCity/Any%20Town
1 > Accept: application/json
1 >
 
14-Mar-2012 4:08:12 PM com.sun.jersey.api.client.filter.LoggingFilter log
INFO: 1 * Client in-bound response
1 < 200
1 < Transfer-Encoding: chunked
1 < Date: Wed, 14 Mar 2012 20:08:12 GMT
1 < Content-Type: application/json
1 < X-Powered-By: Servlet/3.0 JSP/2.2 (GlassFish Server Open Source Edition 3.1.1 Java/Oracle Corporation/1.7)
1 < Server: GlassFish Server Open Source Edition 3.1.1
1 <
[{"address" : {"city" : "Any Town", "id" : 1, "street" : "1 A Street"}, "firstName" : "Jane", "id" : 1, "lastName" : "Doe", "phoneNumbers" : [{"id" : 1, "num" : "555-1111", "type" : "WORK"}, {"id" : 2, "num" : "555-2222", "type" : "HOME"}]}, {"address" : {"city" : "Any Town", "id" : 10, "street" : "456 Another Road"}, "firstName" : "Sue", "id" : 10, "lastName" : "Jones", "phoneNumbers" : [{"id" : 10, "num" : "555-3333", "type" : "WORK"}]}]
 
Doe, Jane
Jones, Sue