tutorial - leer json en java
Consumo de objeto JSON en el servicio de Jersey (5)
Como ya se sugirió, cambiar el @Consumes
Content-Type a text/plain
funcionará, pero no parece correcto desde el punto de vista de REST API.
Imagine que su cliente debe 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
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 de MessageBodyReader para que sepa exactamente cómo funciona. Así es como lo hice:
Paso 1. Implementar un MessageBodyReader personalizado
@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 anterior es comprobar si se espera que la secuencia de entrada se convierta en una String
(especificada por Type genericType
). Si es así, simplemente transfiera el JSON al type
especificado (que será una String
). Si el tipo esperado es algún tipo de POJO, utilice una biblioteca JSON (por ejemplo, Jackson o GSON) para deserializarlo a un POJO.
Paso 2. Vincula tu MessageBodyReader
Esto depende de qué marco estás usando. Me parece que Guice y Jersey trabajan bien juntos. Así es como MessageBodyReader mi MessageBodyReader en Guice:
En mi JerseyServletModule , vinculo al lector como tal -
bind(CustomJsonReader.class).in(Scopes.SINGLETON);
El CustomJsonReader
anterior deserializará las cargas JSON en POJO y también, si simplemente desea los objetos JSON en bruto, String
.
El beneficio de hacerlo de esta manera es que aceptará Content-Type: application/json
. En otras palabras, su controlador de solicitud puede configurarse para consumir JSON, lo que parece apropiado:
@POST
@Path("/stuff")
@Consumes("application/json")
public void doStuff(String json) {
/* do stuff with the json string */
return;
}
He estado buscando en Google mi trasero tratando de descubrir cómo hacer esto: tengo un servicio de REST de Jersey. La solicitud que invoca el servicio REST contiene un objeto JSON. Mi pregunta es, desde la implementación del método Jersey POST, ¿cómo puedo obtener acceso al JSON que está en el cuerpo de la solicitud HTTP?
Cualquier consejo, truco o sugerencia para el código de muestra sería muy apreciado.
Gracias...
--Steve
Envíe / envíe el formulario / HTTP.POST con un parámetro con JSON como valor.
@QueryParam jsonString
public desolveJson (jsonString)
Esto le da acceso a la publicación en bruto.
@POST
@Path("/")
@Consumes("text/plain")
@Produces(MediaType.APPLICATION_JSON)
public String processRequset(String pData) {
// do some stuff,
return someJson;
}
Jersey admite el acceso de bajo nivel al JSONObject analizado utilizando los tipos JetSison 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;
}
Consulte la documentación de Jersey para obtener más ejemplos.
No estoy seguro de cómo llegaría a la cadena JSON en sí, pero ciertamente puede obtener los datos que contiene de la siguiente manera:
Defina una clase de Java anotada JAXB (C) que tiene la misma estructura que el objeto JSON que se está pasando en la solicitud.
por ejemplo, para un mensaje JSON:
{
"A": "a value",
"B": "another value"
}
Use algo como:
@XmlAccessorType(XmlAccessType.FIELD)
public class C
{
public String A;
public String B;
}
Luego, puede definir un método en su clase de recurso con un parámetro de tipo C. Cuando Jersey invoca su método, el objeto JAXB se creará en base al objeto POSTed JSON.
@Path("/resource")
public class MyResource
{
@POST
public put(C c)
{
doSomething(c.A);
doSomethingElse(c.B);
}
}