Saya memiliki hierarki objek yang perlu saya ungkapkan melalui RESTful API dan saya tidak yakin bagaimana URL saya harus terstruktur dan apa yang harus dikembalikan. Saya tidak dapat menemukan praktik terbaik apa pun.
Katakanlah saya memiliki Anjing dan Kucing yang diwarisi dari Hewan. Saya perlu operasi CRUD pada anjing dan kucing; Saya juga ingin bisa melakukan operasi pada hewan secara umum.
Ide pertama saya adalah melakukan sesuatu seperti ini:
GET /animals # get all animals
POST /animals # create a dog or cat
GET /animals/123 # get animal 123
Masalahnya, koleksi / animals sekarang "tidak konsisten", karena koleksi dapat kembali dan mengambil objek yang tidak memiliki struktur yang persis sama (anjing dan kucing). Apakah dianggap "RESTful" memiliki koleksi yang menampilkan objek yang memiliki atribut berbeda?
Solusi lain adalah membuat URL untuk setiap jenis konkret, seperti ini:
GET /dogs # get all dogs
POST /dogs # create a dog
GET /dogs/123 # get dog 123
GET /cats # get all cats
POST /cats # create a cat
GET /cats/123 # get cat 123
Namun kini hubungan antara anjing dan kucing terputus. Jika seseorang ingin mengambil semua hewan, sumber daya anjing dan kucing harus dipertanyakan. Jumlah URL juga akan meningkat dengan setiap subtipe hewan baru.
Saran lain adalah menambah solusi kedua dengan menambahkan ini:
GET /animals # get common attributes of all animals
Dalam kasus ini, hewan yang dikembalikan hanya akan berisi atribut yang umum untuk semua hewan, menghilangkan atribut khusus anjing dan kucing. Ini memungkinkan untuk mengambil semua hewan, meskipun dengan detail yang lebih sedikit. Setiap objek yang dikembalikan dapat berisi tautan ke versi konkret yang mendetail.
Ada komentar atau saran?
sumber
GET /animals - gets all dogs and cats
GET /animals/dogs - gets all dogs
GET /animals/cats - gets all cats
GET /animals
Terimaapplication/vnd.vet-services.animal.dog+json
POST
beroperasi, karena sebagian besar kerangka kerja tidak akan tahu cara mendesentralisasikannya dengan benar ke dalam model karena json tidak membawa info pengetikan yang baik. Bagaimana Anda menangani kasus posting misalnya[{"type":"dog","name":"Fido","playsFetch":true},{"type":"cat","name":"Sparkles","likesToPurr":"sometimes"}
?Pertanyaan ini dapat dijawab dengan lebih baik dengan dukungan dari peningkatan terbaru yang diperkenalkan di versi terbaru OpenAPI.
Skema dapat digabungkan menggunakan kata kunci seperti oneOf, allOf, anyOf, dan mendapatkan payload pesan yang divalidasi sejak skema JSON v1.0.
https://spacetelescope.github.io/understanding-json-schema/reference/combining.html
Namun, di OpenAPI (sebelumnya Swagger), komposisi skema telah ditingkatkan dengan kata kunci diskriminator (v2.0 +) dan oneOf (v3.0 +) untuk benar-benar mendukung polimorfisme.
https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#schemaComposition
Pewarisan Anda dapat dimodelkan menggunakan kombinasi oneOf (untuk memilih salah satu subtipe) dan allOf (untuk menggabungkan tipe dan salah satu subtipe). Di bawah ini adalah contoh definisi untuk metode POST.
sumber
Saya akan pergi untuk / animals mengembalikan daftar anjing dan ikan dan apa lagi:
Harus mudah untuk menerapkan contoh JSON yang serupa.
Klien selalu dapat mengandalkan elemen "nama" yang ada (atribut umum). Tetapi bergantung pada atribut "type", akan ada elemen lain sebagai bagian dari representasi hewan.
Tidak ada yang secara inheren RESTful atau unRESTful dalam mengembalikan daftar seperti itu - REST tidak menentukan format spesifik apa pun untuk merepresentasikan data. Semua yang dikatakannya adalah bahwa data harus memiliki beberapa representasi dan format untuk representasi itu diidentifikasi oleh jenis media (yang dalam HTTP adalah header Jenis Konten).
Pikirkan tentang kasus penggunaan Anda - apakah Anda perlu menunjukkan daftar hewan campuran? Nah, kemudian kembalikan daftar data hewan campuran. Apakah Anda hanya memerlukan daftar anjing? Nah, buatlah daftar seperti itu.
Apakah Anda melakukan / animals? Type = dog atau / dogs tidak relevan sehubungan dengan REST yang tidak menentukan format URL apa pun - yang dibiarkan sebagai detail penerapan di luar cakupan REST. REST hanya menyatakan bahwa resource harus memiliki pengenal - apalagi formatnya.
Anda harus menambahkan beberapa hyper media linking agar lebih dekat dengan RESTful API. Misalnya dengan menambahkan referensi ke detail hewan:
Dengan menambahkan hyper media linking Anda mengurangi penggandengan klien / server - dalam kasus di atas, Anda mengambil beban konstruksi URL dari klien dan membiarkan server memutuskan bagaimana membuat URL (yang menurut definisi adalah satu-satunya otoritas).
sumber
Memang, namun perlu diingat bahwa URI tidak pernah mencerminkan hubungan antar objek.
sumber
Saya tahu ini adalah pertanyaan lama, tetapi saya tertarik untuk menyelidiki masalah lebih lanjut tentang pemodelan warisan RESTful
Saya selalu dapat mengatakan bahwa anjing adalah binatang dan ayam juga, tetapi ayam membuat telur sedangkan anjing adalah mamalia, jadi tidak bisa. Seperti API
DAPATKAN hewan /: animalID / telur
tidak konsisten karena menunjukkan bahwa semua subtipe hewan dapat bertelur (sebagai akibat dari substitusi Liskov). Akan ada kemunduran jika semua mamalia merespons dengan '0' untuk permintaan ini, tetapi bagaimana jika saya juga mengaktifkan metode POST? Haruskah saya takut besok akan ada telur anjing di crepes saya?
Satu-satunya cara untuk menangani skenario ini adalah dengan menyediakan 'sumber daya super' yang menggabungkan semua sub-sumber daya yang dibagi di antara semua 'sumber daya turunan' yang memungkinkan dan kemudian spesialisasi untuk setiap sumber daya turunan yang membutuhkannya, seperti saat kita men-downcast sebuah objek menjadi oop
GET / animals /: animalID / sons GET / hens /: animalID / egg POST / hens /: animalID / telor
Kekurangannya, di sini, seseorang dapat memberikan ID anjing untuk referensi contoh koleksi ayam, tetapi anjing tersebut bukan ayam, jadi tidak salah jika responnya adalah 404 atau 400 dengan pesan alasan
Apakah aku salah?
sumber
Ya kamu salah Juga hubungan dapat dimodelkan mengikuti spesifikasi OpenAPI misalnya dengan cara polimorfik ini.
...
sumber
GET chicken/eggs
juga harus bekerja menggunakan generator kode OpenAPI umum untuk pengontrol, tetapi saya belum memeriksa ini. Mungkin seseorang bisa mencoba?