Pergunta

Eu estive pesquisando minha bunda fora tentando descobrir como fazer isso: Eu tenho um serviço Jersey REST. O pedido que invoca o serviço REST contém um objeto JSON. A minha pergunta é, a partir da implementação do método Jersey POST, como posso obter acesso ao JSON que está no corpo da solicitação HTTP?

Todas as dicas, truques, ponteiros para código de exemplo seria muito apreciada.

Obrigado ...

- Steve

Foi útil?

Solução

Eu não sei como você iria ficar na string JSON em si, mas certamente você pode obter os dados que ele contém o seguinte:

Definir um JAXB anotada classe Java (C) que tem a mesma estrutura que o objeto JSON que está a ser passado sobre o pedido.

por exemplo. para uma mensagem JSON:

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

Use algo como:

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

Em seguida, você pode definir um método em sua classe de recurso com um parâmetro do tipo C. Quando Jersey invoca seu método, o objeto JAXB será criado com base no POSTed JSON objeto.

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

Outras dicas

Como já foi sugerido, mudando o @Consumes Content-Type para text/plain vai funcionar, mas não parece certo do ponto API REST de vista.

Imagine seu cliente tenha de POST JSON à sua API, mas a necessidade de especificar o cabeçalho Content-Type como text/plain. Não é limpo na minha opinião. Em termos simples, se a sua API aceita JSON, em seguida, o cabeçalho de solicitação deve especificar Content-Type: application/json.

Para aceitar JSON mas serializá-lo em um objeto String em vez de um POJO você pode implementar um costume MessageBodyReader . Fazendo dessa forma, é tão fácil, e você não terá que se comprometer a sua especificação API.

Vale a pena ler a documentação para MessageBodyReader para que você saiba exatamente como ele funciona. Isto é como eu fiz isso:

Passo 1. Implementar um costume 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);
  }
}

O conceito básico acima é para verificar se o fluxo de entrada está prevista para ser convertido a um String (especificado por Type genericType). Se assim for, então simplesmente converter o JSON na type especificado (que será um String). Se o tipo esperado é algum tipo de POJO, em seguida, usar uma biblioteca JSON (por exemplo Jackson ou Gson) para desserializar-lo para um POJO.

Passo 2. Ligar o seu MessageBodyReader

Isso depende do que quadro que você está usando. Acho que o trabalho Guice e Jersey bem juntos. Aqui está como eu vincular minha MessageBodyReader em Guice:

Na minha JerseyServletModule eu ligar o leitor como assim -

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

O CustomJsonReader acima deserializará cargas JSON em POJOs, bem como, se você simplesmente quer o JSON cru, objetos String.

A vantagem de fazê-lo desta maneira é que ele irá aceitar Content-Type: application/json. Em outras palavras, seu manipulador de solicitação pode ser configurado para consumir JSON, que parece adequada:

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

Jersey suporta acesso de baixo nível ao JSONObject analisado usando os tipos Jettison JSONObject e JSONArray.

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

Por exemplo:

{
  "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;
}

Veja a documentação Jersey para mais exemplos.

Isto dá-lhe acesso ao pós-prima.

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

Enviar / POST do formulário / HTTP.POST com um parâmetro com o JSON como o valor.

@QueryParam jsonString

desolveJson público (jsonString)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top