Подтвердить что ты не робот

Использование объекта JSON в службе Джерси

Я искал свой приступ, пытаясь выяснить, как это сделать: у меня есть служба REST Джерси. Запрос, который вызывает службу REST, содержит объект JSON. Мой вопрос: с помощью метода метода POST, как я могу получить доступ к JSON, который находится в теле запроса HTTP?

Приветствуются любые советы, трюки, указатели на образец кода.

Спасибо...

- Стив

4b9b3361

Ответ 1

Я не уверен, как вы могли бы получить строку JSON, но вы можете наверняка получить данные, содержащиеся в ней:

Определить JAXB аннотированный класс Java (C), который имеет ту же структуру, что и объект JSON, передаваемый по запросу.

например. для сообщения JSON:

{
  "A": "a value",
  "B": "another value"
}

Используйте что-то вроде:

@XmlAccessorType(XmlAccessType.FIELD)
public class C
{
  public String A;
  public String B;
}

Затем вы можете определить метод в своем классе ресурсов с параметром типа C. Когда Джерси вызывает ваш метод, объект JAXB будет создан на основе объекта POSTed JSON.

@Path("/resource")
public class MyResource
{
  @POST
  public put(C c)
  {
     doSomething(c.A);
     doSomethingElse(c.B);
  }
}

Ответ 2

Как уже было сказано, изменение @Consumes Content-Type на text/plain будет работать, но это не похоже на точку зрения REST API.

Представьте, что ваш клиент имеет POST JSON для вашего API, но должен указать заголовок Content-Type как text/plain. По-моему, это не чистая. Говоря простыми словами, если ваш API принимает JSON, тогда заголовок запроса должен указывать Content-Type: application/json.

Чтобы принять JSON, но сериализуйте его в объект String, а не POJO, вы можете реализовать пользовательский MessageBodyReader. Выполнение этого так же просто, и вам не придется идти на компромисс в спецификации API.

Стоит прочитать документы для MessageBodyReader, чтобы вы точно знали, как это работает. Вот как я это сделал:

Шаг 1. Внедрите пользовательский MessageBodyReader

@Provider
@Consumes("application/json")
public class CustomJsonReader<T> implements MessageBodyReader<T> {
  @Override
  public boolean isReadable(Class<?> type, Type genericType,
      Annotation[] annotations,MediaType mediaType) {
    return true;
  }

  @Override
  public T readFrom(Class<T> type, Type genericType, Annotation[] annotations,
      MediaType mediaType, MultivaluedMap<String, String> httpHeaders,
      InputStream entityStream) throws IOException, WebApplicationException {

    /* Copy the input stream to String. Do this however you like.
     * Here I use Commons IOUtils.
     */
    StringWriter writer = new StringWriter();
    IOUtils.copy(entityStream, writer, "UTF-8");
    String json = writer.toString();

    /* if the input stream is expected to be deserialized into a String,
     * then just cast it
     */
    if (String.class == genericType)
      return type.cast(json);

    /* Otherwise, deserialize the JSON into a POJO type.
     * You can use whatever JSON library you want, here's
     * a simply example using GSON.
     */
    return new Gson().fromJson(json, genericType);
  }
}

Основная концепция, приведенная выше, - проверить, будет ли преобразованный входной поток преобразован в String (указанный Type genericType). Если это так, просто переведите JSON в указанный type (который будет String). Если ожидаемый тип - это своего рода POJO, используйте библиотеку JSON (например, Jackson или GSON), чтобы десериализовать его на POJO.

Шаг 2. Привяжите MessageBodyReader

Это зависит от того, какие рамки вы используете. Я нахожу, что Гиз и Джерси хорошо работают вместе. Вот как я привязываю MessageBodyReader в Guice:

В моем JerseyServletModule Я связываю читателя так:

bind(CustomJsonReader.class).in(Scopes.SINGLETON);

Вышеупомянутый CustomJsonReader будет десериализовать полезную нагрузку JSON в POJO, а также, если вы просто хотите использовать исходные объекты JSON, String.

Преимущество этого в том, что он примет Content-Type: application/json. Другими словами, ваш обработчик запросов может быть настроен на использование JSON, что кажется правильным:

@POST
@Path("/stuff")
@Consumes("application/json") 
public void doStuff(String json) {
  /* do stuff with the json string */
  return;
}

Ответ 3

Джерси поддерживает низкоуровневый доступ к анализируемому JSONObject с использованием типов JTONObject и JSONArray типа Jettison.

<dependency>
    <groupId>org.codehaus.jettison</groupId>
    <artifactId>jettison</artifactId>
    <version>1.3.8</version>
</dependency>

Например:

{
  "A": "a value",
  "B": "another value"
}


@POST
@Path("/")
@Consumes(MediaType.APPLICATION_JSON) 
public void doStuff(JSONObject json) {
  /* extract data values using DOM-like API */
  String a = json.optString("A");
  Strong b = json.optString("B");
  return;
}

Подробнее см. документацию Джерси.

Ответ 4

Это дает вам доступ к исходному сообщению.

@POST
@Path("/")
@Consumes("text/plain") 
@Produces(MediaType.APPLICATION_JSON)
public String processRequset(String pData) {
    // do some stuff, 
    return someJson;
}

Ответ 5

Отправить/POST форму /HTTP.POST с параметром с JSON в качестве значения.

@QueryParam jsonString

public desolveJson (jsonString)