API REST - L'API dovrebbe restituire oggetti JSON nidificati?

30

Quando si tratta di API JSON è buona norma appiattire le risposte ed evitare oggetti JSON annidati?

Ad esempio, diciamo che abbiamo un'API simile a IMDb ma per i videogiochi. Ci sono un paio di entità, Game, Platform, ESRBRating e GamePlatformMap che mappe Games and Platforms.

Diciamo che richiedi / game / 1 che recupera il gioco con ID 1 e restituisce l'oggetto di gioco con le piattaforme e la posizione di esrb annidata.

{
  "id": 1,
  "title": "Game A",
  "publisher": "Publisher ABC",
  "developer": "Developer DEF",
  "releaseDate": "2015-01-01",
  "platforms": [
    {"id":1,"name":"Xbox"},
    {"id":2,"name":"Playstation"}
  ],
  "esrbRating": {
    "id": 1,
    "code": "E",
    "name": "Everyone"
  }
}

Se stai usando qualcosa come JPA / Hibernate, potrebbe farlo automaticamente se è impostato su FETCH.EAGER.

L'altra opzione è semplicemente l'API e aggiungi più punti finali.

In questo caso quando viene richiesto / game / 1 viene restituito solo l'oggetto del gioco.

{
  "id": 1,
  "title": "Game A",
  "publisher": "Publisher ABC",
  "developer": "Developer DEF",
  "releaseDate": "2015-01-01",
}

Se vuoi le piattaforme e / o ESRBRating dovresti chiamare quanto segue:

/ gioco / 1 / piattaforma / Gioco / 1 / CERS

Questo metodo sembra che potrebbe potenzialmente aggiungere molte altre chiamate al server a seconda dei dati di cui il client ha bisogno e quando ne hanno bisogno.

C'era un ultimo pensiero che avevo in cui avresti restituito qualcosa di simile.

{
  "id": 1,
  "title": "Game A",
  "publisher": "Publisher ABC",
  "developer": "Developer DEF",
  "releaseDate": "2015-01-01",
  "platforms": ["Xbox","Playstation"]
}

Tuttavia, si presume che non abbiano bisogno degli ID o di qualunque altra informazione possa essere associata a quegli oggetti della piattaforma.

Chiedo in generale quale sia il modo migliore per strutturare gli oggetti JSON restituiti dalla tua API. Dovresti provare a stare il più vicino possibile alle tue entità, o è meglio usare Oggetti Dominio o Oggetti di Trasferimento Dati? Capisco che i metodi avranno compromessi, più lavoro sul livello di accesso ai dati o più lavoro per il cliente.

Vorrei anche ascoltare una risposta relativa all'utilizzo di Spring MVC come tecnologia di backend per l'API, con JPA / Hibernate o MyBatis per la persistenza.

    
posta greyfox 09.02.2015 - 01:16
fonte

3 risposte

9

Un'altra alternativa (usando HATEOAS). Questo è semplice, per lo più in pratica aggiungi un tag link in json a seconda dell'utilizzo di HATEOAS.

http://api.example.com/games/1 :

{
  "id": 1,
  "title": "Game A",
  "publisher": "Publisher ABC",
  "developer": "Developer DEF",
  "releaseDate": "2015-01-01",
  "platforms": [
    {"_self": "http://api.example.com/games/1/platforms/53", "name": "Playstation"},
    {"_self": "http://api.example.com/games/1/platforms/34", "name": "Xbox"},
  ]
}

http://api.example.com/games/1/platforms/34 :

{
  "id": 34,
  "title": "Xbox",
  "publisher": "Microsoft",
  "releaseDate": "2015-01-01",
  "testReport": "http://api.example.com/games/1/platforms/34/reports/84848.pdf",
  "forms": [
    {"type": "edit", "fields: [] },
  ]
}

Ovviamente è possibile incorporare tutti i dati in tutti gli elenchi, ma probabilmente saranno troppi dati. In questo modo puoi incorporare i dati richiesti e poi caricarne altri se vuoi davvero lavorarci sopra.

L'implementazione tecnica può contenere il caching. È possibile memorizzare nella cache i collegamenti e i nomi delle piattaforme nell'oggetto del gioco e inviarlo immediatamente senza dover caricare l'API della piattaforma. Quindi, quando richiesto, è possibile caricarlo.

Si vede ad esempio che ho aggiunto alcune informazioni sul modulo. L'ho fatto per mostrarti che ci possono essere molte più informazioni in un oggetto json dettagliato di quello che vorresti caricare nella lista dei giochi.

    
risposta data 09.02.2015 - 06:46
fonte
15

Questa è una di quelle domande di base quando si tratta della progettazione dell'API REST. Ogni designer si pone questa domanda il primo giorno. Scusa ma la risposta è "dipende". Ogni approccio ha pro e contro e dovrai solo prendere una decisione e seguirla.

    
risposta data 09.02.2015 - 03:16
fonte
5

In secondo luogo, l'approccio presentato qui link

In breve, includere la risorsa nidificata come collegamenti nella risorsa genitore, nel frattempo, fornire un parametro di espansione nell'endpoint principale.

Secondo me, questo è un modo efficiente e flessibile nella maggior parte dei casi.

    
risposta data 28.09.2017 - 12:29
fonte

Leggi altre domande sui tag