json - tutorial - servicios rest ejemplo
¿Cómo puedo pasar objetos complejos como argumentos a un servicio RESTful? (3)
Después de cavar un poco, rápidamente descubrí que hay básicamente dos opciones:
Opción 1
Pasas un "objeto contenedor" que contiene todos los otros parámetros al servicio. Es posible que necesite anotar esta clase de envoltura con anotaciones JAXB como @XmlRootElement para que esto funcione con el proveedor basado en Jettison, pero si usa Jackson en su lugar no es necesario. Simplemente configure el tipo de contenido al tipo correcto y se invocará el lector del cuerpo del mensaje correcto. Esto solo funcionará para servicios de tipo POST por supuesto (AFAIK).
Ejemplo
Este es solo un ejemplo de cómo convertir el servicio mencionado en la pregunta original en uno usando un objeto envoltorio.
@Service("myService")
class RestService {
@POST
@Produces("application/json")
@Path("/fooBar")
public Result fooBar(
/**
* Using "" will inject all form params directly into a ParamsWrapper
* @see http://cxf.apache.org/docs/jax-rs-basics.html
*/
@FormParam("") FooBarParamsWrapper wrapper
) throws WebServiceException {
doSomething(wrapper.foo);
}
}
class ParamsWrapper {
double foo, bar;
MyComplexObject object;
}
opcion 2
Puede proporcionar algún formato de cadena especial en el que empaquetar sus objetos y luego implementar un constructor que tome una cadena, un valueOf estático (String s) o una cadena estática (String s) en la clase que tomará esta cadena y creará un objeto. de eso. O bastante similar, cree un ParameterHandler que haga exactamente lo mismo.
AFAIK, solo la segunda versión le permitirá llamar a sus servicios desde un navegador usando JSONP (ya que JSONP es un truco restringido a GET). Elegí esta ruta para poder pasar matrices de objetos complejos en el URI.
Como ejemplo de cómo funciona esto, tome la siguiente clase de dominio y servicio
Ejemplo
@GET
@Path("myService")
public void myService(@QueryParam("a") MyClass [] myVals) {
//do something
}
class MyClass {
public int foo;
public int bar;
/** Deserializes an Object of class MyClass from its JSON representation */
public static MyClass fromString(String jsonRepresentation) {
ObjectMapper mapper = new ObjectMapper(); //Jackson''s JSON marshaller
MyClass o= null;
try {
o = mapper.readValue(jsonRepresentation, MyClass.class );
} catch (IOException e) {
throw new WebApplicationException()
}
return o;
}
}
Un URI http://my-server.com/myService?a={"foo":1, "bar":2}&a={"foo":100, "bar":200}
en este caso sería deserializado en una matriz compuesta de dos objetos MyClass.
He configurado con éxito una prueba rápida para crear un servicio "similar a REST" que devuelve un objeto serializado a JSON, y fue bastante fácil y rápido (basado en este artículo ).
Pero al devolver objetos JSON-ified fue fácil como melocotón, todavía tengo que ver ejemplos que traten con parámetros de entrada que no sean primitivos. ¿Cómo puedo pasar un objeto complejo como argumento? Estoy usando Apache CXF, pero los ejemplos que usan otros marcos como Jackson también son bienvenidos :)
El lado del cliente probablemente sería algo como construir un objeto javascript, pasarlo a JSON.stringify (complexObj) y pasar esa cadena como uno de los parámetros.
El servicio probablemente se vería así.
@Service("myService")
class RestService {
@GET
@Produces("application/json")
@Path("/fooBar")
public Result fooBar(@QueryParam("foo") double foo, @QueryParam("bar") double bar,
@QueryParam("object") MyComplex object) throws WebServiceException {
...
}
}
El envío de objetos serializados como parámetros probablemente toque rápidamente el límite de URL de 2 KB impuesto por Internet Explorer. ¿Recomendaría usar POST en estos casos y necesitaría cambiar mucho en las definiciones de funciones?
La respuesta aceptada falta @BeanParam. Consulte https://docs.jboss.org/resteasy/docs/3.0-rc-1/javadocs/javax/ws/rs/BeanParam.html para obtener más detalles. Le permite definir parámetros de consulta dentro de un objeto contenedor. P.ej
public class TestPOJO {
@QueryParam("someQueryParam")
private boolean someQueryParam;
public boolean isSomeQueryParam() {
return someQueryParam;
}
public boolean setSomeQueryParam(boolean value) {
this.someQueryParam = value;
}
}
... // inside the Resource class
@GET
@Path("test")
public Response getTest(@BeanParam TestPOJO testPOJO) {
...
}
la mejor y más simple solución es enviar su objeto como una cadena json y, en el lado del servidor, implementar un método que decodifique ese json y se asigne al objeto especificado según sus necesidades ... y sí, es mejor usar POST.