I am trying to understand How I could use JSON-SCHEMA, particularly
the 'links' sub schema to represent the following typicall REST like
interaction where some properties of an object are Read (GET) only and
some are Update (PUT) only.
Suppose I have an class of objects 'O' which can be accessed from the
URI ' /collection/{id} '
O supports 3 propoerties
O.id, O.name, O.state where..
O.id is a read only property
O.name is Read / write and must be set on creation.
O.state is also read only and can be either 'active', 'suspended'
O.action is Write only and can be either 'activate' or 'suspend'
O.desc is Read / Write but cannot be set on Creation and is not
returned in GET's to the containing collection.
So typical interactions might include..
O's can be created with a POST to the /objects collection..
<< POST /objects { "name":"oname" }
>> LOCATION: /objects/1
O's properties can also be retrieved on a GET to the collection
<< GET /objects
>> [ { "id":1, "name":"omame", "state":"suspended" ]
I can also initate an action on O and update the Descsription with a
PUT..
<< PUT /objects/1 { "action":"suspend", "desc":"Description" }
>> LOCATION: /objects/1
Full Details of O's properties (except 'action') can then also
retrieved by a direct GET..
<< GET /objects/1
>> { "id":1, "state":"suspended", "name":"oname",
"desc":"Description" }
So my question is how could (or should) JSON-SCHEMA be used to
represent this kind of Object. The closest I can come up with is ...
{
"name":"Object",
"properties":{
"id": { "type": "integer" }
"name": { "type": "string" },
"desc": {
"type": "string"
"optional":true },
"action":{
"type": "string",
"optional":true,
"enum": ["suspend", "activate"],
},
"state":{
"type": "string",
"enum": "active", "suspended"
}
}
},
"links":[
{ "rel":"instances",
"href":"/objects",
"method":"GET"
}
{ "rel":"full",
"href":"/objects/{id}",
"method":"GET"
},
{ "rel":"create",
"href":"/objects",
"method":"POST",
"properties":[
{ "name": { } }
]
}
{ "rel":"update",
"href":"/objects/{id}",
"method":"PUT",
"properties":
{ "name": { } },
{ "desc": { } },
{ "action":{ } },
}
{ "rel":"delete",
"href":"/objects/{id}"
"method":"DELETE"
}
]
}
Is this correct?
Is there any other way to specify permissions on properties as 'read-
only?'
Is there also any way to specify what the response of a PUT or POST or
DELETE might be be? (ie LOCATION headers etc,,)
How is it possible to specify that only certain properties should be
returned on an 'instances' GET vs a 'full' GET.
Thanks,
mat
You can use the "readonly" attribute to indicate that a property is read
only (http://tools.ietf.org/html/draft-zyp-json-schema-02#section-6.4).
"id": {
"type": "integer",
"readonly": true}
},
....
> Is there also any way to specify what the response of a PUT or POST or
> DELETE might be be? (ie LOCATION headers etc,,)
>
No, the HTTP specification should provide adequate detail for
interpreting responses (meaning of headers, etc). Is there something it
misses?
> How is it possible to specify that only certain properties should be
> returned on an 'instances' GET vs a 'full' GET.
>
That is something that the server decides before it send the document to
the client, and therefore a normative definition for hiding properties
is not necessary for the purposes of communicating the required
structure of the transferred document (since it is not visible to the
client). Naturally servers can utilize their own properties for defining
hidden properties, for example in Pintura I use a "blocked" attribute.
> Is this correct?
Your schema looks mostly correct. However, you shouldn't specify
update/PUT and delete/DELETE relations (section 6.1.1.3.1.). These are
not link/relations, they are actions/methods, and well defined by the
HTTP spec. Respecifying them in a schema is redundant and potentially
confusing (if they conflicted with HTTP semantics).
Also it might worth considering alternate ways of communicating your
"suspend" and "activate" actions. I believe the HTTP spec specifies that
PUT should send the representation of the resource, as it would expect
to later receive on a GET. By having your PUT body contain an "action",
where the GET contains a "state" somewhat deviates from expectation (and
would result in an incorrect cache entry if an intermediary cached the
PUT's body). I think it is helpful to think of PUT is a request by the
client for a resource to be mutated to the requested state, and letting
the server decide what action needs to take place to get the resource
into that state (for example, PUTing an altered "state" property, and
letting the server determine if it needs to suspend or activate). On the
otherhand a POST is a request by a client for some specific action to be
carried out, and letting the server decide what state changes that
results in. For example, you could define your "suspend" and "activate"
actions like this:
"links":[
{ "rel":"activate",
"href":"/objects/{id}/activate",
"method":"POST"
},
{ "rel":"suspend",
"href":"/objects/{id}/suspend",
"method":"POST"
},
...
But, that is just a suggestion, your approach is reasonable, and perhaps there are user interface/interaction aspects that have shaped your design.
Anyway, your design looks good, cool to see JSON Schema really being leveraged :).
--
Thanks,
Kris