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 tiene que ENVIAR JSON a su API pero necesita especificar el encabezado Content-Type como text/plain
. No está limpio en mi opinión. En términos simples, si su API acepta JSON, el encabezado de la solicitud debe especificar Content-Type: application/json
.
Para aceptar JSON pero serializarlo en un objeto String
en lugar de un POJO, puede implementar un MessageBodyReader personalizado. Hacerlo de esta manera es igual de fácil, y no tendrá que comprometer sus especificaciones de API.
Vale la pena leer los documentos 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 a convertir en un String
(especificado por Type genericType
)Si es así, simplemente transfiera el JSON al type
especificado (que será un String
). Si el tipo esperado es algún tipo de POJO, utilice una biblioteca JSON (por ejemplo, Jackson o GSON) para deserializarlo en un POJO.
Paso 2. vincular a su MessageBodyReader
Esto depende de qué marco que está utilizando. Me parece que Guice y Jersey trabajan bien juntos. Así es como me ato mi MessageBodyReader en Guice:
En mi JerseyServletModule Ato el lector como tal -
bind(CustomJsonReader.class).in(Scopes.SINGLETON);
Lo anterior CustomJsonReader
se deserializar cargas útiles JSON en POJOs, así como, si simplemente desea que la prima JSON, String
objetos.
El beneficio 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;
}
estoy enfrentando el problema similar. ¿hay alguna solución para usar acceso de bajo nivel a JSONObject? – Jugi