2014-10-29 10 views
10

Poszukuję najlepszego sposobu zaprojektowania niestandardowej odpowiedzi JSON dla RESTful API w Grails na podstawie tej prezentacji Design Beautiful REST + JSON APIs przez Les Hazlewood.Interfejs REST API Grails - Renderuj JSON z stronicowaniem, metadanymi i niestandardowymi zawiera pola z paramerów

Oto moja klasa Domain

class TaxiType { 

    Date dateCreated, lastUpdated 
    String description 
    User createdBy 

    static hasMany = [taxis: Taxi] 

    static constraints = { 
    } 
} 

żądany format odpowiedź na liście jest

{ 
    "meta": { 
    "href": "https://api.mydomain.com/taxi-types", 
    "otherData": "..." 
    }, 
    "paging": { 
    "offset": 0, 
    "limit": 10, 
    "total": 100, 
    "first": "https://api.mydomain.com/taxi-types?offset=0&limit=10", 
    "previous": null, 
    "next": "https://api.mydomain.com/taxi-types?offset=90&limit=10", 
    "last": "https://api.mydomain.com/taxi-types?offset=90&limit=10" 
    }, 
    "data": [ 
    { 
     "href": "https://api.mydomain.com/taxi-types/1", 
     "id": 1, 
     "description": "description 1", 
     "taxis": { 
     "href": "https://api.mydomain.com/taxi-types/1/taxis" 
     } 
    }, 
    ... 
    ] 
} 

TaxiTypeController.groovy

def index(Integer limit) { 
    params.max = Math.min(limit ? : 10, 100) 
     params.offset = params ? .offset ? .toInteger() 
     withFormat { 
     json { 
      respond TaxiType.list(params), 
      [includes : includeFields, 
       paging : [total : TaxiType.count(), limit : params ? .max, offset : params ? .offset ? : 0] 
      ] 
     } 
    } 
} 
private getIncludeFields() { 
    params.fields ? .tokenize(', ') 
} 

SumoJsonCollectionRenderer.groovy

class SumoJsonCollectionRenderer extends JsonCollectionRenderer { 
    SumoJsonCollectionRenderer(Class componentType) { 
     super(componentType) 
    } 
    public SumoJsonCollectionRenderer(Class componentType, MimeType...mimeTypes) { 
     super(componentType, mimeTypes) 
    } 
    @ CompileStatic(SKIP) 
    @ Override 
    protected void renderJson(object, RenderContext context) { 
     log.debug(object) 
     log.debug(object.size()) 
     log.debug(object.getTotalCount()) 
     Map tObject = ['data' : object] 
     if (context.arguments ? .paging) { 
      tObject['paging'] = context ? .arguments ? .paging 
     } 
     super.renderJson(tObject, context) 
    } 
} 

Wymagane cechy to:

1) API użytkownicy powinni być w stanie uzyskać tylko wymagane pola (częściowe reprezentacje)

GET https://api.mydomain.com/taxi-types??fields=id,description,taxis 

pożądana odpowiedź na ten wniosek powinien być

{ 
    "meta" : {...} 
    "paging" : {...} 
    "data" : [{ 
      "href" : "https://api.mydomain.com/taxi-types/1", 
      "id" : 1, 
      "description" : "Taxi Type1", 
      "taxis" : [{ 
        "href" : "https://api.mydomain.com/taxis/123" 
       }, 
       ... 
      ] 
     }, 
     ... 
    ] 
} 

To, co otrzymuję, to:

{ 
    "data" : [{ 
      "id" : 1, 
      "description" : "Taxi Type1", 
      "taxis" : [{ 
        "class" : "com.domain.project.Taxi", 
        "id" : 1 
       } 
      ] 
     }, 
     ... 
    ], 
    "paging" : { 
     "total" : 80, 
     "limit" : 10, 
     "offset" : 0 
    } 
} 

Przekazałem odpowiedź na to pytanie Render metadata for pagination from Grails RestfulController index/search actions.

Ale nadal trzeba dołączyć linki do strony first, previous, next & last w przywoływaniu, jak wspomniano w pożądanym formacie powyżej.

2) Dostosowywanie wyświetlamy

np właściwość z hasMany związek taxis należy zapewnić domyślnie jako

"taxis": { 
    "href": "https://api.mydomain.com/taxis/12345" 
} 

i jeżeli użytkownik preferuje rozszerzyć taxis właściwości, na np: GET /taxi-types?expand=taxis , format JSON powinien być

"taxis": { 
    "href": "https://api.mydomain.com/taxis/12345" 
    "name": "Taxi name", 
    "type": "https://api.mydomain.com/taxi-types/1" 
    ... 
} 

3) Dodaj meta obiektu do wszystkich odpowiedzi

"meta": { 
    "href": "https://api.mydomain.com/taxi-types", 
    ... 
} 

próbowałem JSON naziemnego dostosować odpowiedzi. Oto mój kod naziemnego

JSON.registerObjectMarshaller(TaxiType) {TaxiType taxiType-> 
    return [ 
     id : taxiType ? .id, 
     description : taxiType ? .description 
    ] 
} 

ale zawsze czyni z tych dwóch właściwości w tablicy powrotnej id & description, nawet jeśli chcę niektóre inne właściwości, takie jak taxis.

W jaki sposób można zastosować 3 wymagania ?. Z góry dziękuję.

+3

Oto kilka przykładów, które mogą Ci się przydać: http://mrhaki.blogspot.com/2014/07/grails-goodness-using-converter-named.html Zobacz także "Related Posts" na dole strona, artykuły i notatniki mrhaki są doskonałym źródłem dla wszystkich rzeczy Groovy i Grails. –

+0

To pytanie ma wiele przydatnych informacji ... używam go jako odpowiedzi (!) – Rafael

Odpowiedz

0

Stworzyłem plugin for grails 3, który pozwala na dodawanie stronicowania, niestandardowych metadanych i innych przydatnych funkcji do apisa. Możesz dodać funkcje HAL, używając również LinkGenerators wraz z moją wtyczką.

Powiązane problemy