RESTful API design. ¿Qué debo devolver si no hay filas?

50

Actualmente estoy codificando una API para una red social con Slim Framework. Mi pregunta es: ¿Cuáles son las mejores prácticas cuando no hay filas para regresar en la estructura json?

Digamos que esta llamada / v1 / get / movies devuelve 2 filas de los nombres de las películas de la tabla:

[
    {"name": "Ghostbusters"},
    {"name": "Indiana Jones"}
]

Pero luego llamo / v1 / get / books y no hay filas en esa tabla. ¿Debo devolver una estructura vacía?

[
]

... ¿O sería mejor un mensaje y un código de error?

[
    "errors": {
        "message": "no matches found",
        "code": 134
    }
]

¿Cuál es una mejor práctica? (la API se utilizará en aplicaciones iOS y Android) ¡Gracias!

    
pregunta Andres SK 29.05.2013 - 08:09

14 respuestas

45

Por lo general, devolvería el número de registros del resultado como metadatos. No estoy seguro de si esa es la práctica normal de REST, pero no son muchos datos adicionales y son muy precisos. Por lo general, hay paginación para muchos servicios, no es práctico devolver un gran conjunto de resultados a la vez. Personalmente estoy molesto cuando hay paginación para pequeños conjuntos de resultados. Si está vacío, devuelve number_of_records : 0 y los libros como lista vacía / matriz books : [] .

{
    meta: {
        number_of_records : 2,
        records_per_page : 10,
        page : 0
    },
    books : [
        {id:1},
        {id:27}
    ]
}

EDITAR (unos años más tarde): La respuesta de Martin Wickman es mucho mejor, aquí hay una explicación "corta" de por qué.

Cuando se trata de paginación, siempre tenga en cuenta la posibilidad de que los contenidos o el orden cambien. Al igual que, la primera solicitud llega, 24 resultados, usted regresa el primer 10. Después de eso, se inserta "nuevo libro" y ahora tiene 25 resultados, pero con la solicitud original, se ordenaría en el décimo lugar. Cuando el primer usuario solicita la 2ª página, no obtendría "libro nuevo". Hay formas de manejar tales problemas, como proporcionar "id de solicitud" que debe enviarse con las siguientes llamadas a la API, y luego regresar a la página siguiente del conjunto de resultados "antiguo", que debe almacenarse de alguna manera y estar vinculado a "id de solicitud". La alternativa es agregar un campo como "la lista de resultados ha cambiado desde la primera solicitud".

En general, si puede, intente esforzarse más y evite la paginación. La paginación es un estado adicional que se puede mutar y el seguimiento de dichos cambios es propenso a errores, incluso más porque el servidor y el cliente necesitan manejarlo.

Si tiene demasiados datos para procesar a la vez , considere devolver la "lista de identificación" con todos los resultados y detalles de una parte de esa lista, y proporcione las llamadas a la API multi_get / get_by_id_list para el recurso.

    
respondido por el GrizzLy 29.05.2013 - 08:52
105

Tu ejemplo está roto. No debes tener objetos json con claves duplicadas. Lo que está buscando es una matriz con objetos de película, como este:

 [
    {"name": "movie1"}, 
    {"name": "movie2"}
 ]

Este enfoque también responde a tu pregunta. Debería devolver una matriz vacía cuando la consulta no coincida:

[]

Por otro lado, si intenta obtener un recurso de película específico con GET api/movie/34 y esa película no existe, entonces devuelva 404 con un mensaje de error adecuado (codificado en json) en el cuerpo

    
respondido por el Martin Wickman 29.05.2013 - 10:27
15

Si esto es JSON, realmente debería considerar devolver una matriz de objetos. Esto tiene muchas ventajas, incluido que cuando no tiene registros es una matriz vacía.

Entonces, cuando tengas registros, estarías regresando:

    [
        {"name": "Ghostbusters"},
        {"name": "Indiana Jones"}
    ]

Y cuando no tengas registros, estarías regresando:

    [

    ]
    
respondido por el Devdatta Tengshe 29.05.2013 - 09:10
14

Si ejecuta la operación con éxito, pero no tiene nada que devolver, como el mapa vacío {} o la matriz vacía [] Preferiría responder con el código de respuesta 204, aquí está un extracto de Definiciones de códigos de estado de HTT especificación:

  

El servidor ha cumplido la solicitud, pero no necesita devolver un cuerpo de entidad, y puede querer devolver información actualizada. La respuesta PUEDE incluir metainformación nueva o actualizada en forma de encabezados de entidad, que si están presentes DEBEN asociarse con la variante solicitada.

     

Si el cliente es un agente de usuario, NO DEBE cambiar su vista de documento desde la que causó el envío de la solicitud. El objetivo principal de esta respuesta es permitir que se realicen acciones sin que se produzca un cambio en la vista de documento activo del agente del usuario, aunque cualquier información nueva o actualizada DEBE aplicarse al documento que se encuentra actualmente en la vista activa del agente del usuario.

     

La respuesta 204 NO DEBE incluir un cuerpo del mensaje, por lo que siempre termina con la primera línea vacía después de los campos de encabezado.

Esencialmente, recomiendo usar 204 en aplicaciones RESTful sobre HTTP cuando no hay nada que devolver.

    
respondido por el David Sergey 29.05.2013 - 14:01
10

Se ha realizado una cantidad razonable de trabajo para crear un formato de API JSON estandarizado .

Seguir los principios en esa especificación significa que todos los recursos devueltos deberían ser efectivamente "colecciones" (incluso cuando se incluye un solo recurso). Seguir esto significaría que su llamada a /v1/get/movies regresaría:

{
    "movies": [
        {"name": "Ghostbusters"},
        {"name": "Indiana Jones"}
    ]
}

Su llamada a /v1/get/books (que devuelve cero recursos) devolverá:

{
    "books": []
}
    
respondido por el Tim Blair 29.05.2013 - 19:44
5

Para su ejemplo específico, recomendaría que / v1 / get / books devuelva HTTP 200 con una matriz vacía.

Si estoy leyendo correctamente tu publicación, tu API pretende recopilar libros. Hablando metafóricamente, tienes una estantería para libros, un estante de DVD para películas y posiblemente otros contenedores que no has mencionado aquí. Como tiene la intención de recopilar libros, / v1 / get / books es su biblioteca. Esto significa que hay un recurso válido allí, una lista de libros, que está vacío en su ejemplo específico.

La razón por la que no sugiero que se devuelva HTTP 404 en este caso es que la estantería todavía está allí. No hay libros sobre él en este momento, pero sigue siendo una estantería. Si no fuera una biblioteca -si la API no tuviera la intención de recopilar libros, por ejemplo- , entonces HTTP 404 sería apropiado. Pero como hay un recurso allí, no debe indicar que no hay uno, lo que hace HTTP 404. Por lo tanto, sostengo que 200 con una matriz vacía (que significa la colección) es más apropiado.

La razón por la que no sugiero que se devuelva HTTP 204 es que esto sugeriría que "Sin Contenido" es el estado normal de las cosas: realizar esta acción en este recurso normalmente no devolvería nada. Es por eso que por lo general se usa como respuesta a las solicitudes DELETE, por ejemplo: la naturaleza de la eliminación generalmente significa que no queda nada por devolver. El caso es similar cuando se usa para responder solicitudes con la familia de encabezados modificados por If: solo querías contenido si el recurso había cambiado, pero no lo hizo, así que no te daré ningún contenido.

Pero sostengo que para obtener una colección vacía pero válida, HTTP 204 no tiene sentido. Si hubiera elementos en la colección, entonces la representación adecuada sería una matriz de esos datos. Por lo tanto, cuando no hay datos allí (pero la recopilación es válida), la representación adecuada es una matriz vacía.

    
respondido por el The Spooniest 06.02.2014 - 20:14
5

Realmente deberías hacer solo una de dos cosas

O bien Devuelve un código de estado 200 (OK) y una matriz vacía en el cuerpo.

o Devuelva un código de estado 204 (NO CONTENT) y NO cuerpo de respuesta.

Para mí, la opción 2 parece más correcta desde el punto de vista técnico y en línea con los principios REST y HTTP.

Sin embargo, la opción 1 parece ser más eficiente para el cliente, porque el cliente no necesita lógica adicional para diferenciar entre dos códigos de estado (de éxito). Ya que sabe que siempre recibirá una matriz, simplemente tiene que verificar si no tiene ninguno, uno o muchos elementos y procesarlos de manera adecuada

    
respondido por el Vihung 29.09.2014 - 18:48
3

He visto ambos casos en entornos de producción. La opción que elija dependerá de quién utilizará la API. Si quieren saber por qué la lista está vacía o para estar seguros de que la lista está realmente vacía y no se produjeron errores al recuperarla, debe adjuntar un objeto de "errores". Si no les importa, regresa con una lista vacía. Me quedaría con el segundo enfoque, ya que cubre más necesidades que el primero.

    
respondido por el devnull 29.05.2013 - 08:49
3

Lo primero a considerar, ya que está creando una API RESTful, es devolver un código de respuesta apropiado. Y el código de respuesta más apropiado para comunicar que la solicitud se realizó normalmente, pero el recurso solicitado no está disponible en este momento es el venerable 404.

Si diseña su API de tal manera que siempre devuelva un código de respuesta razonable, es posible que ni siquiera necesite devolver un cuerpo cuando no se encontró el recurso. Dicho esto, devolver un cuerpo, especialmente uno legible por humanos, no puede hacer daño.

No hay "mejores prácticas" aquí, ambos ejemplos son arbitrarios, solo elija uno y sea consistente . Los desarrolladores odian las sorpresas, si /v1/get/movies devuelve {} cuando no hay películas, entonces esperamos que /v1/get/actors también devuelva {} cuando no haya actores.

    
respondido por el yannis 29.05.2013 - 08:49
1

No creo que la respuesta correcta sea la que está marcada.

La respuesta proporcionada por nirth debe ser la mejor, en un verdadero escenario REST. La respuesta del cuerpo debe estar vacía y el código de estado http: 204; el recurso existe pero no tiene "contenido" en ese momento: está vacío.

REST HTTP_Status_Codes

    
respondido por el jmmtcarvalho 04.06.2013 - 11:32
1

Recomiendo 200+ array vacío, ya que simplifica el manejo por todos los clientes de la API. 200 + array significa "Devolví todos los datos que están allí". Tanto en el código que entrega los datos como en el código que los procesa, el número de elementos sería irrelevante.

Todos los demás códigos de estado deben estar debidamente documentados y entregados por el servidor y procesados adecuadamente por el cliente, y todos sabemos qué posibilidades hay de que esto suceda.

Hubo una sugerencia para devolver el estado 204 + cuerpo vacío. Eso significa que obliga a a cada único cliente a procesar el estado 204 correctamente. ¡Además, los obligas a manejar las respuestas que no son JSON! Espero que todos se den cuenta de que solo porque una solicitud obtuvo una respuesta, no significa que la respuesta provino del servidor cuando se usa http, y solo una verificación de que la respuesta es JSON maneja muchos de esos casos.

    
respondido por el gnasher729 22.11.2015 - 14:57
0

Yo lo haría "Depende".

Si cero es un resultado razonable, devuelva la lista vacía. Por ejemplo, si desea obtener todos los empleados llamados "bob" donde "ninguno" es un resultado bastante razonable. Si no es un resultado esperado devuelve un error. Por ejemplo, obtener una lista histórica de las direcciones de las calles de una persona que emplee. Deben vivir en algún lugar , por lo que probablemente no haya un resultado, es solo un error, no solo una condición normal.

Estoy seguro de que puedes discutir los detalles de mi ejemplo, pero entiendes la idea ...

    
respondido por el JohnB 06.02.2014 - 13:58
0
  • En primer lugar, tener get en tu URL no es RESTful, GET está implícito en el método HTTP.
  • Si estás solicitando una colección como GET api/movies , devuelve un 200 OK con una matriz vacía [] .
  • Si solicita una película específica como GET api/movies/1 (donde 1 es el id) y no existe, devuelva un 404 Not Found .

¿Por qué? Estás solicitando recursos . Cuando solicita la colección, el recurso en sí (la colección) existe. Por lo tanto, un 404 es incorrecto. Pero si solicita una película específica y no existe, el recurso solicitado no existe y debe devolver un 404 .

    
respondido por el felixfbecker 22.11.2015 - 13:35
-2

Si está devolviendo JSON, es mejor devolver siempre el recuento y el mensaje de error y tal vez un booleano que indique si hay un error o no, es decir, mis tres valores meta estándar devueltos con cada lista de filas.

    
respondido por el sino 22.11.2015 - 15:12

Lea otras preguntas en las etiquetas

Comentarios Recientes

Se han exportado muchas funciones "definidas con subrayado" desde libydb, el motor de recopilación disponible desde el punto final de entrada, y clientes como Viewer o las bibliotecas restangulares desean los tipos de datos de destino, como un rango o lista de listas, devueltas como valores requeridos. Por ejemplo, "json" es útil para enviar una base de datos a los clientes. Los documentos, modelos y esquemas XML se limitan a campos con nombre o rutas de origen dados y sus valores se devuelven de una de dos maneras:... Lee mas