Рубрики
Без рубрики

Примеры Джерси и JSON (Джексон)

Как использовать Джексона в качестве поставщика JSON в Джерси, пользовательский объектный картограф Джексона, пользовательский картограф исключений JSON, проверить ответ JSON и т. Д.

В этой статье показано, как вернуть JSON ответ в приложении Джерси , используя Jackson 2.x .

Протестировано с

  • Джерси 3.0.2
  • HTTP-сервер Grizzly 3
  • Джексон 2.12.2
  • Java 11
  • Знаток
  • JUnit 5 и JSONassert 1.5 (Модульный тест)

Содержание

  • 1. Джексон как поставщик JSON в Джерси
  • 2. Каталог проектов
  • 3. Зависимости проекта
  • 4. Конечные точки Джерси и возвращают ответ JSON
  • 5. Запустите приложение Джерси
  • 6. ДЕМОНСТРАЦИЯ
  • 7. Пользовательский картограф объектов Джексона в Джерси
    • 7.1 Включите режим печати Jackson pretty
    • 7.2 Зарегистрируйте пользовательский сопоставитель объектов Джексона в ResourceConfig
    • 7.3 Демонстрация с включенной симпатичной печатью
  • 8. Пользовательское исключение JsonMappingException в Джерси
    • 8.1 Пользовательское исключение JsonMappingException
    • 8.2 Зарегистрируйте пользовательское исключение JsonMappingException в ResourceConfig
    • 8.3 ДЕМОНСТРАЦИЯ с пользовательским исключением JsonMappingException
  • 9. Модульное тестирование конечных точек JSON Джерси
  • 10. Скачать Исходный Код
  • 11. Рекомендации

1. Джексон как поставщик JSON в Джерси

Мы можем включить джерси-медиа-json-Джексон , чтобы включить Джексона в качестве поставщика JSON в приложении Джерси.

  
  
      org.glassfish.jersey.media
      jersey-media-json-jackson
  

2. Каталог проектов

Просмотрите каталог стандартных проектов Maven.

3. Зависимости проекта

Просмотрите зависимости проекта.



    4.0.0

    com.mkyong
    jersey-json-example
    jar
    1.0

    
        UTF-8
        11
        11
        11
        5.4.0
        1.5.0
        3.0.2
    

    
        
            
                org.glassfish.jersey
                jersey-bom
                ${jersey.version}
                pom
                import
            
        
    

    

        
        
            org.glassfish.jersey.containers
            jersey-container-grizzly2-http
        

        
        
            org.glassfish.jersey.inject
            jersey-hk2
        

        
        
            org.glassfish.jersey.media
            jersey-media-json-jackson
        

        
        
            jakarta.activation
            jakarta.activation-api
            2.0.1
        

        
        
            org.junit.jupiter
            junit-jupiter-params
            ${junit.version}
            test
        

        
        
            org.skyscreamer
            jsonassert
            ${jsonassert.version}
            test
        

    

    
        jersey-json-jackson
        
            
                org.apache.maven.plugins
                maven-compiler-plugin
                3.8.1
                
                    ${java.version}
                    ${java.version}
                
            

            
            
                org.apache.maven.plugins
                maven-surefire-plugin
                3.0.0-M5
            

            
                org.apache.maven.plugins
                maven-jar-plugin
                3.2.0
                
                    
                        
                            true
                            lib/
                            com.mkyong.MainApp
                        
                    
                
            

            
            
                org.apache.maven.plugins
                maven-dependency-plugin
                3.1.2
                
                    
                        copy-dependencies
                        package
                        
                            copy-dependencies
                        
                        
                            
                            runtime
                            ${project.build.directory}/lib/
                        
                    
                
            

        
    


4. Конечные точки Джерси и возвращают ответ JSON

Создайте несколько конечных точек в Джерси, и Джексон обработает преобразование объекта из/в JSON.

4.1 Создайте следующие конечные точки и верните ответ JSON.

  • GET /json/ , возвращает строку JSON.
  • ПОЛУЧИТЬ /json/{имя} , возвращает Пользователь объект, содержащий {имя} в строке JSON.
  • ПОЛУЧИТЬ /json/все , возвращает список Пользовательских объектов в строке JSON.
  • СООБЩЕНИЕ /json/создать , принимает данные JSON и возвращает статус 201 .
package com.mkyong.json;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;

import java.util.Arrays;
import java.util.List;

@Path("/json")
public class JsonResource {

    private static final ObjectMapper mapper = new ObjectMapper();

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response hello() {

        // create a JSON string
        ObjectNode json = mapper.createObjectNode();
        json.put("result", "Jersey JSON example using Jackson 2.x");
        return Response.status(Response.Status.OK).entity(json).build();
    }

    // Object to JSON
    @Path("/{name}")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public User hello(@PathParam("name") String name) {
        return new User(1, name);
    }

    // A list of objects to JSON
    @Path("/all")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public List helloList() {
        return Arrays.asList(
                new User(1, "mkyong"),
                new User(2, "zilap")
        );
    }

    @Path("/create")
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response create(User user) {

        ObjectNode json = mapper.createObjectNode();
        json.put("status", "ok");
        return Response.status(Response.Status.CREATED).entity(json).build();

    }

}

4.2 Ниже приведен объект User ; позже Джексон преобразует этот объект в/из строки JSON.

package com.mkyong.json;

public class User {

  private int id;
  String name;

  public User() {
  }

  public User(int id, String name) {
      this.id = id;
      this.name = name;
  }

  //  getters and setters
}

5. Запустите приложение Джерси

Запускает приложение Джерси по адресу http://localhost:8080 .

package com.mkyong;

import com.mkyong.json.JsonResource;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
import org.glassfish.jersey.server.ResourceConfig;

import java.io.IOException;
import java.net.URI;
import java.util.logging.Level;
import java.util.logging.Logger;

public class MainApp {

    public static final URI BASE_URI = URI.create("http://localhost:8080");

    // Starts Grizzly HTTP server
    public static HttpServer startHttpServer() {

        final ResourceConfig config = new ResourceConfig();
        config.register(JsonResource.class);
        // JacksonFeature for JAXB/POJO, for pure JSON, no need this JacksonFeature
        // config.register(JacksonFeature.class);

        return GrizzlyHttpServerFactory.createHttpServer(BASE_URI, config);
    }

    public static void main(String[] args) {

        try {

            final HttpServer server = startHttpServer();

            server.start();

            // shut down hook
            Runtime.getRuntime().addShutdownHook(new Thread(server::shutdownNow));

            System.out.println(
              String.format("Application started.%nStop the application using CTRL+C"));

            // block and wait shut down signal, like CTRL+C
            Thread.currentThread().join();

        } catch (InterruptedException | IOException ex) {
            Logger.getLogger(MainApp.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

}

6. ДЕМОНСТРАЦИЯ

Запускает Основное приложение и использует инструмент cURL для простого тестирования.

$ curl http://localhost:8080/json
{"result":"Jersey JSON example using Jackson 2.x"}

$ curl http://localhost:8080/json/mkyong
{"id":1,"name":"mkyong"}

$ curl http://localhost:8080/json/all
[{"id":1,"name":"mkyong"},{"id":2,"name":"zilap"}]

# send a POST request with JSON data
$ curl -H "Content-Type: application/json"
    -X POST -d "{\"id\" : 1,\"name\" : \"mkyong\"}" http://localhost:8080/json/create

{"status":"ok"}

7. Пользовательский картограф объектов Джексона в Джерси

В приведенной выше демонстрации ответ JSON находится в компактном режиме, поведение по умолчанию Jackson ObjectMapper ; и мы можем создать пользовательское приложение Jackson ObjectMapper в Джерси, реализовав класс JAX RS ContextResolver .

7.1 Включите режим печати Jackson pretty

Ниже приведен пример, создайте пользовательский файл Jackson ObjectMapper , чтобы включить режим красивой печати.

package com.mkyong.json;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import jakarta.ws.rs.ext.ContextResolver;
import jakarta.ws.rs.ext.Provider;

// enable Jackson pretty print
@Provider
public class CustomJacksonMapperProvider
  implements ContextResolver {

  final ObjectMapper mapper;

  public CustomJacksonMapperProvider() {
      // enable pretty print
      mapper = new ObjectMapper()
              .enable(SerializationFeature.INDENT_OUTPUT);
  }

  @Override
  public ObjectMapper getContext(Class type) {
      return mapper;
  }

}

7.2 Зарегистрируйте пользовательский сопоставитель объектов Джексона в ResourceConfig

  public static HttpServer startHttpServer() {

      final ResourceConfig config = new ResourceConfig();
      config.register(JsonResource.class);

      // register the custom Jackson mapper
      config.register(CustomJacksonMapperProvider.class);

      return GrizzlyHttpServerFactory.createHttpServer(BASE_URI, config);
  }

7.3 Демонстрация с включенной симпатичной печатью

Снова запускает Основное приложение , и теперь ответ JSON находится в красивой строке печати.

$ curl http://localhost:8080/json/java
{
  "id" : 1,
  "name" : "java"
}

$ curl http://localhost:8080/json/all
[ {
  "id" : 1,
  "name" : "mkyong"
}, {
  "id" : 2,
  "name" : "zilap"
} ]

8. Пользовательское исключение JsonMappingException в Джерси

Мы пытаемся ОПУБЛИКОВАТЬ нераспознанное поле в /json/создать , и Джерси вернет подробное сообщение по умолчанию.

$ curl -H "Content-Type: application/json"
    -X POST -d "{\"id-error-field\" : 1,\"name\" : \"mkyong\"}" http://localhost:8080/json/create

Unrecognized field "id-error-field" (class com.mkyong.json.User), not marked as ignorable (2 known properties: "id", "name"])
 at [Source: (org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream); line: 1, column: 22]
 (through reference chain: com.mkyong.json.User["id-error-field"])

8.1 Пользовательское исключение JsonMappingException

Мы можем создать пользовательский ExceptionMapper для перехвата JsonMappingException ошибки и возврата нашего пользовательского ответа JSON.

package com.mkyong.json;

import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.ext.ExceptionMapper;
import jakarta.ws.rs.ext.Provider;

@Provider
public class CustomJsonExceptionMapper
      implements ExceptionMapper {

  private static final ObjectMapper mapper = new ObjectMapper();

  @Override
  public Response toResponse(JsonMappingException exception) {

      ObjectNode json = mapper.createObjectNode();
      //json.put("error", exception.getMessage());
      json.put("error", "json mapping error");
      return Response.status(Response.Status.BAD_REQUEST)
              .entity(json.toPrettyString())
              .build();
  }

}

8.2 Зарегистрируйте пользовательское исключение JsonMappingException в ResourceConfig

    public static HttpServer startHttpServer() {

        final ResourceConfig config = new ResourceConfig();
        config.register(JsonResource.class);
        config.register(CustomJacksonMapperProvider.class);

        // custom ExceptionMapper
        config.register(CustomJsonExceptionMapper.class);

        return GrizzlyHttpServerFactory.createHttpServer(BASE_URI, config);
    }

8.3 ДЕМОНСТРАЦИЯ с пользовательским исключением JsonMappingException

Снова запускает Основное приложение , и мы ОТПРАВЛЯЕМ нераспознанное поле в /json/создаем снова, и теперь Джерси вернет ваш пользовательский ответ в формате JSON.

$ curl -H "Content-Type: application/json"
    -X POST -d "{\"id-error-field\" : 1,\"name\" : \"mkyong\"}" http://localhost:8080/json/create

{
  "error" : "json mapping error"
}  

9. Модульное тестирование конечных точек JSON Джерси

Ниже приведен JUnit 5 и JSONAssert пример для тестирования конечных точек JSON Джерси.

package com.mkyong;

import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.Entity;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.glassfish.grizzly.http.server.HttpServer;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.skyscreamer.jsonassert.JSONAssert;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class JsonResourceTest {

  private static HttpServer server;
  private static WebTarget target;

  @BeforeAll
  public static void beforeAllTests() {
      server = MainApp.startHttpServer();
      Client c = ClientBuilder.newClient();
      target = c.target(MainApp.BASE_URI.toString());
  }

  @AfterAll
  public static void afterAllTests() {
      server.shutdownNow();
  }

  @Test
  public void testJson() throws JSONException {

      String actual = target.path("json").request().get(String.class);
      String expected = "{\"result\":\"Jersey JSON example using Jackson 2.x\"}";

      JSONAssert.assertEquals(expected, actual, false);

  }

  @Test
  public void testJsonName() throws JSONException {

      String response = target.path("json/mkyong")
              .request(MediaType.APPLICATION_JSON)
              .get(String.class);

      // convert json string to JSONObject
      JSONObject actual = new JSONObject(response);

      String expected = "{\"id\":1,\"name\":\"mkyong\"}";
      JSONAssert.assertEquals(expected, actual, false);

  }

  @Test
  public void testJsonAll() throws JSONException {

      String response = target.path("json/all")
              .request(MediaType.APPLICATION_JSON)
              .get(String.class);

      // convert json string to JSONArray
      JSONArray actual = new JSONArray(response);

      String expected = "[{\"id\":1,\"name\":\"mkyong\"},{\"id\":2,\"name\":\"zilap\"}]";
      JSONAssert.assertEquals(expected, actual, false);

  }

  @Test
  public void testJsonCreateOk() throws JSONException {

      String json = "{\"id\":1,\"name\":\"mkyong\"}";

      Response response = target.path("json/create")
              .request(MediaType.APPLICATION_JSON)
              .post(Entity.entity(json, MediaType.valueOf("application/json")));

      assertEquals(Response.Status.CREATED.getStatusCode(), response.getStatus());

      // read response body
      String actual = response.readEntity(String.class);
      String expected = "{\"status\":\"ok\"}";
      JSONAssert.assertEquals(expected, actual, false);

  }

  @Test
  public void testJsonCreateError() throws JSONException {

      String json = "{\"id_no_field\":1,\"name\":\"mkyong\"}";

      Response response = target.path("json/create")
              .request(MediaType.APPLICATION_JSON)
              .post(Entity.entity(json, MediaType.valueOf("application/json")));

      assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), response.getStatus());

      String actual = response.readEntity(String.class);
      String expected = "{\"error\":\"json mapping error\"}";
      JSONAssert.assertEquals(expected, actual, false);
  }

}

10. Скачать Исходный Код

$клон git https://github.com/mkyong/jax-rs

$cd jax-rs/джерси/джерси-json-джексон/

$ пакет mvn

$цель java-jar/джерси-json- $цель java-jar/джерси-json-

11. Рекомендации

Оригинал: “https://mkyong.com/webservices/jax-rs/json-example-with-jersey-jackson/”