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ę.
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. –
To pytanie ma wiele przydatnych informacji ... używam go jako odpowiedzi (!) – Rafael