Let's say I'm building an API to handle appointments. An appointment consists of a Doctor, a Patient, and a set of Cares.
If I want to create an appointment, what should the POST data look like? Please note that only the appointment would get created with this query. The doctor, patient, and cares entries already exist in the database.
I've got 2 options:
{
doctor_id: 8,
patient_id: 4,
cares_ids:
[1,7]
}
{
doctor: {
id: 8,
name: 'Dr James Brown',
phone: '107-102-304',
address: '16th avenue'
},
patient: {
id: 4,
name: 'Mr Elvis',
pathology: 'Blah Blah.'
},
cares:
[
{
id: 1,
name: 'Dental cares'
},
{
id: 7,
name: 'Back pain'
}
]
}
The short one feels cleaner, as we are not sending useless data like name and address etc. But the second one feels more natural/semantic in my front-end code.
For example in my application, I would only have to do:
appointment.doctor = selected_doctor
// Instead of doing
appointment.doctor_id = selected_doctor.id
Are there any RESTful best practices for this kind of case?
In fact, you're facing to the issue of relations. OData provides solution to this problem called "navigation properties". Perhaps this could give you some hints on the way to fixed this problem. You can have a look at these links for more details: http://www.odata.org/getting-started/basic-tutorial/ and http://www.odata.org/getting-started/advanced-tutorial/
In fact, there are several issues here:
I think that the complete representation you give in your question corresponds to what you expect to have when getting an appointment, i.e. the appointment data included the data of relations like doctor, patient and cares.
Such hints aren't all necessary to link an appointment to other elements like doctor and patient. Only the identifiers matter. I think that you could have a different representation for the appointment creation. At this level setting the reference to element is enough. So you could have somethinhg like that:
POST /appointments
{
doctor-ref: http://.../doctors/8,
patient-ref: http://.../patients/4,
cares-ref: [ http://.../cares/1, http://.../cares/7 ]
}
or
POST /appointments
{
[email protected]: http://.../doctors/8,
[email protected]: http://.../patients/4,
[email protected]: [ http://.../cares/1, http://.../cares/7 ]
}
In the same way, you could define additional resources to be able to update these links after the appointment was created without sending all the content. We could imagine something like that:
Single cardinality
PUT /appointments/<appointmentid>/doctor
{ [email protected]: http://.../doctors/8 }
Multiple cardinality
POST /appointments/<appointmentid>/cares
{ metadata.ref: http://.../cares/8 }
DELETE appointments/<appointmentid>/cares
{ metadata.ref: http://.../cares/8 }
You can notice that you can also choose not to retrieve all appointment data for an appointment (if it's something interesting for you). Here is the different representations you could have:
Complete
{
doctor: {
id: 8,
name: 'Dr James Brown',
phone: '107-102-304',
address: '16th avenue'
},
patient: {
id: 4,
name: 'Mr Elvis',
pathology: 'Blah Blah.'
},
cares:
[
{
id: 1,
name: 'Dental cares'
},
{
id: 7,
name: 'Back pain'
}
]
}
}
Parial with links / references
{
[email protected]: http://.../doctors/8,
patient: {
id: 4,
name: 'Mr Elvis',
pathology: 'Blah Blah.'
},
[email protected]: [ http://.../cares/1, http://.../cares/7 ]
}
or
{
[email protected]: http://.../doctors/8,
patient: {
id: 4,
name: 'Mr Elvis',
pathology: 'Blah Blah.'
},
cares:
[
{
id: 1,
name: 'Dental cares'
},
{
id: 7,
name: 'Back pain'
}
]
}
}
This feature corresponds in OData to the query parameter $expand.
You could have a look at this link: http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/entity-relations-in-odata-v4. See sections "Getting Related Entities", "Creating a Relationship Between Entities" and "Deleting a Relationship Between Entities". It could give hints for your representation.
The last part of the question is related to the way to build the representation (for creation for example). I don't know exactly the technology you use but in Java, you can do something like that appointment.doctor = selected_doctor and adapt a bit the serialization of your objects to create something like that [email protected]: http://.../doctors/8 from an instance of Doctor. For example with Jackson2, it's called custom serializer (see this link http://www.baeldung.com/jackson-custom-serialization for example).
Hope it helps you, Thierry
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With