Pregunta

He estado buscando en Google mi trasero tratando de encontrar la manera de hacer esto: Tengo un servicio REST Jersey. La solicitud que invoca el servicio REST contiene un objeto JSON. Mi pregunta es, a partir de la implementación del método Jersey POST, ¿cómo puedo tener acceso a los JSON que se encuentra en el cuerpo de la petición HTTP?

Cualquier consejos, trucos, punteros a ejemplo de código sería muy apreciada.

Gracias ...

- Steve

¿Fue útil?

Solución

No estoy seguro de cómo puede conseguir en la propia cadena JSON, pero que sin duda puede conseguir en los datos que contiene la siguiente manera:

Definir un JAXB anotada Java clase (C) que tiene la misma estructura que el objeto JSON que se pasa en la solicitud.

por ejemplo. para un mensaje JSON:

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

Utilice algo como:

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

A continuación, se puede definir un método en su clase de recurso con un parámetro de tipo C. Cuando Jersey invoca el método, el objeto JAXB se creará en función del objeto JSON publicado.

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

Otros consejos

Como ya se ha sugerido, el cambio de la @Consumes Content-Type a text/plain va a funcionar, pero no me parece bien desde el punto de vista de la API REST.

Imagine que su cliente tenga que apostar JSON a su API, pero que necesitan para especificar la cabecera Content-Type como text/plain. No es limpio en mi opinión. En términos simples, si su API acepta JSON entonces el encabezado de la solicitud debe especificar Content-Type: application/json.

Para aceptar JSON serializar pero en un objeto String en lugar de un POJO se puede implementar un encargo MessageBodyReader . Hacerlo de esta manera es tan fácil, y usted no tendrá que ceder en su especificación API.

Vale la pena leer la documentación para MessageBodyReader para que sepa exactamente cómo funciona. Esto es cómo lo hice:

Paso 1. Implementar una costumbre 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);
  }
}

El concepto básico de arriba es para comprobar si se espera que el flujo de entrada que ser convertido a un String (especificado por Type genericType). Si es así, entonces simplemente emitir el JSON en el type especificado (que será un String). Si el tipo esperado es una especie de POJO, a continuación, utilizar una biblioteca JSON (por ejemplo, Jackson o GSON) deserializar a un POJO.

Paso 2. vincular a su MessageBodyReader

Esto depende de qué marco que está utilizando. Encuentro que Guice y Jersey trabajan bien juntos. Así es como me ato mi MessageBodyReader en guice:

JerseyServletModule ato al lector al igual que -

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

El CustomJsonReader anterior se deserializar cargas útiles JSON en POJOs, así como, si simplemente desea que el JSON prima, objetos String.

La ventaja de hacerlo de esta manera es que aceptará Content-Type: application/json. En otras palabras, el controlador de solicitudes se puede configurar para consumir JSON, lo que parece adecuado:

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

Jersey soporta acceso de bajo nivel a la JSONObject analizada usando los tipos jettison JSONObject y JSONArray.

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

Por ejemplo:

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

Vea la documentación Jersey para más ejemplos.

Esto le da acceso al puesto prima.

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

Presentar / POST la forma / HTTP.POST con un parámetro con el JSON como el valor.

@QueryParam jsonString

desolveJson pública (jsonString)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top