RESTful API tasarımı. Satır yoksa ne geri dönmeliyim?


50

Şu anda Slim Framework ile bir sosyal ağ için bir API kodluyorum. Sorum şu: Json yapısında döndürülecek satır olmadığında en iyi uygulamalar nelerdir?

Diyelim ki bu çağrı / v1 / get / movies , tablodaki film adlarından 2 satır döndürüyor:

[
    {"name": "Ghostbusters"},
    {"name": "Indiana Jones"}
]

Ama sonra / v1 / get / books'i çağırdım ve bu tabloda hiç satır yok. Sadece boş bir yapıya döneyim mi?

[
]

... yoksa mesaj ve hata kodu daha iyi olur mu?

[
    "errors": {
        "message": "no matches found",
        "code": 134
    }
]

Hangisi daha iyi bir uygulamadır? (API, iOS ve Android uygulamalarında kullanılacaktır) Teşekkürler!


3
Bana göre bu sıfırın gerçekten bir miktar olup olmadığı sorusu gibi geliyor.
eşarp

16
Örneğin bozuldu. Yinelenen tuşları olan bir json nesnesi olamaz. Aradığın şey bir dizi, yani[{"name": "..."}, {"name":"..."}]
Martin Wickman

@ MartinWickman Bunun için üzgünüm, sadece düzelttim.
Andres SK

8
@ andufo, aslında, sen ...
avakar

25
Başvurunuz RESTful olması gerekiyorsa, neden fiil / yöntem son nokta URI'nizin bir parçası "olsun"?
kullanıcı50849

Yanıtlar:


46

Genellikle sonuçta meta veri olarak sonuçların sayısını döndürürdüm. Bunun normal bir REST uygulaması olup olmadığından emin değilim, ancak fazladan bir veri değil ve çok kesin. Genellikle birçok hizmetin sayfalandırılması vardır, bir kerede büyük sonuçların döndürülmesi pratik değildir. Şahsen küçük sonuç kümeleri için sayfalama olduğunda sinirlenirim. Boşsa number_of_records : 0, boş liste / dizi olarak geri dönün ve kitapları çıkarın books : [].

{
    meta: {
        number_of_records : 2,
        records_per_page : 10,
        page : 0
    },
    books : [
        {id:1},
        {id:27}
    ]
}

EDIT (birkaç yıl sonra): Martin Wickman'dan cevap çok daha iyi, işte nedenini açıklatan "kısa".

Sayfalama ile uğraşırken her zaman içindekiler veya değişiklik sırasını değiştirme olasılığını göz önünde bulundurun. Gibi, ilk istek geliyor, 24 sonuç, ilk 10'a dönersiniz. Bundan sonra, "yeni kitap" eklenir ve şimdi 25 sonuç alırsınız, ancak orijinal istekle 10. sırada yer alır. İlk kullanıcı 2. sayfayı istediğinde, "yeni kitap" alamazdı. Aşağıdaki API çağrılarıyla gönderilmesi gereken "istek kimliği" ni sağlamak, ardından bir şekilde saklanıp "istek kimliği" ile ilişkilendirilmesi gereken "eski" sonuç kümesinden sonraki sayfayı döndürmek gibi bu tür sorunları çözmenin yolları vardır. Alternatif, "ilk istekden bu yana sonuç listesi değişti" gibi bir alan eklemek.

Genel olarak, eğer yapabilirseniz, fazladan çaba göstermeye ve sayfalama yapmaktan kaçının. Sayfalandırma, mutasyona uğratılabilen ve bu değişiklikleri takip edebilen ek durumdur, hataya açıktır, daha da fazladır, çünkü hem sunucunun hem de istemcinin bunu yapması gerekir.

Aynı anda işlenemeyecek kadar çok veriye sahipseniz, o listenin bir kısmı için tüm sonuçlar ve ayrıntılarla birlikte "id list" i döndürmeyi düşünün ve kaynak için multi_get / get_by_id_list API çağrıları sağlayın.


1
Huh, bunun neden diğeri kadar yüksek oy kullanmadığını merak ediyorum. Bunu, hem özel bir şart olmaksızın kör bir şekilde yineleyebileceğiniz, hem de bir liste olması gerekiyordu, bir liste olması gerekiyordu, ama aynı zamanda meta verilerini dediğiniz gibi, "Hayır, yapmadık" demesinin bir listesini veriyor. t bir hatadan bahsedin, aslında 0 sonuç vardı ".
Izkata

1
-1, çünkü booksparametre bir nesnedir, ancak 'kitaplar' birden fazla ve birden fazla dizi ifade eder. Meta veri harika ve hepsi ama sonuçta bir kitap koleksiyonunun bir kitap nesneleri dizisi olmasını bekliyorum; kitap yoksa, sadece bana boş diziyi verin
Charles Sprayberry 4:

9
Bununla ilgili sorun, "number_of_records" eklemek, daha fazla bilgi sağlamaz, yalnızca fazlalık ekler ve karmaşıklığı arttırır. Bir hatayı işaret etmek için gövdede uygun bir http kodu + bir şey döndürün.
Martin Wickman

1
@ cspray kitapları listesi, İzkata'nın işaret ettiği gibi yazım hatası.
grizwako

2
@MartinWickman Özgün yanıtı fazladan meta verilerle kirletmek istemedim, ancak deneyimlerime göre birçok hizmet tüm verileri hemen değil, "sayfalandırılmış" biçimde döndürüyor.
grizwako

105

Örneğin bozuldu. Yinelenen tuşları olan json nesneleriniz olmamalıdır. Aradığın şey şunun gibi film nesnelerinin bulunduğu bir dizi :

 [
    {"name": "movie1"}, 
    {"name": "movie2"}
 ]

Bu yaklaşım aynı zamanda sorunuzu da cevaplar. Sorgu eşleşmediğinde boş bir dizi döndürmelisiniz :

[]

Öte yandan, belirli bir film kaynağını almaya çalışırsanız GET api/movie/34ve bu film yoksa, gövdede uygun (json kodlu) bir hata mesajı ile 404'ü döndürün


1
+1 Bu, JSON’a göre geçerlidir json_xs.
l0b0

15

Bu JSON ise, gerçekten bir nesne dizisi döndürmeyi düşünmelisiniz. Bu, hiç kaydınız olmadığında boş bir dizi olması gibi birçok avantaja sahiptir.

Yani kayıtların olduğunda, geri döneceksin:

    [
        {"name": "Ghostbusters"},
        {"name": "Indiana Jones"}
    ]

Ve hiç kaydın olmadığında, geri döneceksin:

    [

    ]

14

İşlemi başarıyla yürütürseniz, ancak boş harita {}veya boş dizi gibi geri döndürülecek bir şeyi yoksa [], 204 yanıt koduyla yanıt vermeyi tercih ederim, işte HTTP Durum Kodu Tanımlamaları belirtiminden alıntılar :

Sunucu isteği yerine getirdi, ancak bir varlık gövdesi döndürmesi gerekmiyor ve güncellenmiş metainformation geri dönmek isteyebilir. MAY yanıtı, eğer varsa talep edilen değişkenle ilişkili olması gereken varlık başlıkları biçimindeki yeni veya güncellenmiş metainformasyonları içerir.

İstemci bir kullanıcı aracısıysa, isteğinin gönderilmesine neden olandan belge görünümünü değiştirmemelidir. Bu yanıtın öncelikle, kullanıcı aracısının etkin belge görünümünde bir değişiklik yapmadan eylemlerin gerçekleşmesine izin verilmesi amaçlanmıştır, ancak kullanıcı aracının etkin görünümünde mevcut belgeye yeni veya güncellenmiş herhangi bir meforformasyon uygulanmalıdır.

204 yanıtı bir mesaj gövdesi İÇERMEMELİDİR ve bu nedenle başlık alanlarından sonraki her zaman ilk boş satırla sonlandırılır.

Temel olarak, geri döndürecek bir şey olmadığında 204'ü HTTP üzerinden RESTful uygulamalarında kullanmanızı öneririm.


4
@ Avakar'ın buradaki diğer cevaplarla ilgili yorumuna katılıyorum. Eğer müşteri / v1 / get / movies / 1 'e erişmeye çalışıyorsa, 1 ile tanımlanabilecek bir film yoksa 404' e dönmelidir. Ancak 204 uygun değildir çünkü girdi işlemleri için tasarlanmıştır.
imel96

7
Bu çözümle ilgili başka bir sorun, istemcide tipik olarak özel bir koda ihtiyaç duymasıdır: Yanıt boş bir liste ise, normal bir yanıt gibi JSON olarak ayrıştırılabilir. Yanıt boş bir gövdeyse, JSON ayrıştırıcısı büyük olasılıkla şikayet edecektir (boş bir belge geçerli JSON olmadığı için), bu nedenle istemcinin HTTP 204'ü kontrol etmek ve ayrıştırmayı atlamak için fazladan koda ihtiyacı vardır.
sleske

7
Bunun 204 niyetinin yanlış okunması olduğuna inanıyorum. 204, içeriği beklenen ve hiçbir şeyi bulamayan işlemler için değil, başarılı ve amaçlanan geri dönüşleri olmayan işlemler için tasarlandı . Wikipedia'dan: "Sunucu isteği başarıyla işleme koymuştur, ancak içerik döndürmemektedir. Genellikle başarılı bir silme isteğine yanıt olarak kullanılır."
XML,

10

Standart bir JSON API formatı oluşturmak için makul miktarda çalışma yapılmıştır .

Bu şartnamede belirtilen ilkelere uymak, geri gönderilen tüm kaynakların etkin bir şekilde "koleksiyonlar" olması gerektiği anlamına gelir (sadece tek bir kaynak dahil edildiğinde bile). Bunu takiben aramanızın /v1/get/moviesgeri döneceği anlamına gelir :

{
    "movies": [
        {"name": "Ghostbusters"},
        {"name": "Indiana Jones"}
    ]
}

/v1/get/books(Sıfır kaynak döndüren) çağrınız geri döner:

{
    "books": []
}

5

Özel bir örnek olarak, / v1 / get / books’in HTTP 200’ü boş bir diziyle döndürmesini tavsiye ederim.

Yayınınızı doğru okuyorsam, API’niz kitap toplamayı hedefliyor. Mecazi olarak konuşursak, kitaplar için bir kitaplığınız, filmler için bir DVD rafınız ve muhtemelen burada bahsetmediğiniz diğer kaplarınız var. Kitap toplamak niyetinde olduğunuz için, / v1 / get / books kitaplığınızdır. Bu, sizin örneğinizde boş görünen bir kitap listesi olan geçerli bir kaynak olduğu anlamına gelir.

Bu durumda HTTP 404'ü iade etmemi önermemin nedeni kitaplığın hala orada olmasıdır. Şu anda üzerinde hiç kitap yok, ama yine de bir kitaplık. Eğer bir kitaplık olmasaydı - mesela eğer API kitap toplama niyetinde değilse, o zaman HTTP 404 uygun olurdu. Fakat orada bir kaynak olduğu için, HTTP 404'ün bir tane olmadığını işaret etmemelisiniz. Bu nedenle, 200'ün boş bir diziyle (koleksiyonu belirten) daha uygun olduğunu savunuyorum.

HTTP 204'ü döndürmeyi önermememin nedeni, bunun "İçerik Yok" un normal durum olduğu anlamına gelmesidir: bu işlemi bu kaynakta yapmak normalde hiçbir şey döndürmez. Bu nedenle, genellikle DELETE isteklerine bir cevap olarak kullanılır, örneğin: silme niteliği genellikle geri döndürecek bir şey kalmayacağı anlamına gelir. Durum, If-Modified başlık ailesi ile yapılan taleplere cevap vermek için kullanıldığında benzerdir: yalnızca kaynak değiştiyse içerik istediniz, ancak değişmedi, bu yüzden size herhangi bir içerik vermeyeceğim.

Ancak boş ama geçerli bir koleksiyonu almak için HTTP 204'ün bir anlam ifade etmediğini savunuyorum. Koleksiyonda öğeler varsa, o zaman doğru temsil bu verinin bir dizisi olacaktır. Bu nedenle, orada hiçbir veri olmadığı zaman (ancak koleksiyon geçerlidir), uygun temsil boş bir dizilimdir.


5

Gerçekten iki şeyden sadece birini yapmalısın

Bir 200 (OK)durum kodu veya gövdede boş bir dizi döndürün.

Veya Bir 204 (NO CONTENT)durum kodu ve NO yanıt gövdesi döndürün.

Bana göre, seçenek 2 daha teknik olarak doğru görünüyor ve REST ve HTTP ilkeleri ile uyumlu.

Bununla birlikte, seçenek 1 müşteri için daha verimli görünüyor - çünkü müşterinin iki (başarı) durum kodunu ayırt etmek için ekstra bir mantığa ihtiyacı yok. Her zaman bir dizi alacağını bildiğinden, yalnızca bir, bir veya daha fazla öğe alıp almadığını kontrol etmek ve uygun şekilde işlem yapmak zorundadır.


3

Her iki vakayı da üretim ortamlarında gördüm. Hangisini seçtiğiniz, API'yi kimin kullanacağına bağlıdır. Listenin neden boş olduğunu bilmek veya listenin gerçekten boş olduğundan emin olmak ve geri alırken hiçbir hata oluşmasını istemiyorlarsa, bir "hata" nesnesi eklemelisiniz. Önemsemiyorlarsa, boş bir liste döndürerek devam edin. Birincisinden daha fazla ihtiyacı karşıladığı için ikinci yaklaşıma giderdim.


3

Dikkate alınacak ilk şey, bir RESTful API oluşturduğunuz için uygun bir yanıt kodu döndürmektir. Ve isteğin normal şekilde gerçekleştiğini bildirmek için daha uygun yanıt kodu, ancak istenen kaynak şu anda kullanılamıyor 404.

API'nizi her zaman mantıklı bir yanıt kodu döndürecek şekilde tasarlarsanız, kaynak bulunmadığında bir gövdeyi geri döndürmeniz gerekmeyebilir. Bununla birlikte, özellikle insan tarafından okunabilen bir cesedi iade etmek zarar veremez.

Burada "en iyi uygulama" yoktur, her iki örneğiniz de keyfidir, sadece birini seçin ve tutarlı olun . Geliştiriciler sürprizlerden nefret eder, film olmadığında /v1/get/moviesgeri dönerse {}, oyuncu olmadığında /v1/get/actorsda geri dönmeyi {}umarız.


1
Bir 404'ü geri vermek gerçekten yapılacak doğru şeydir, ama ne yazık ki kimse bunu yapmaz - kendim dahil.
RibaldEddie

1
karmaşık yanıtlarınız varsa ve yalnızca bir kısmı boşsa, 404'ü geri vermek kullanıcının kafasını karıştırır.
devnull

5
404 mesaja katılmıyorum. Bir 404, "kaynak mevcut değil" olarak yorumlanır ve URL'mde ya da her neyse yanlış bir şey olursa endişelenirim. Bir film listesi isteyip 404 elde edersem, hiç bir film kaynağı olmadığını düşünürdüm. Bir "204 İçerik Yok" daha uygun olabilir.
thorsten müller

8
Tamam, "vücut yok" olayı onu öldürür. Ancak: "4xx durum kodu sınıfı, müşterinin hatalı gözüktüğü durumlar için tasarlanmıştır.". Ancak müşteri tarafında hata yoktu. Yani bir 404 yanlış bilgi veriyor. Gövdesiz ya 204 yolla ya da tamam diyip boş bir liste gönder
thorsten müller

9
Bir kitap listesi istiyorsun, 404'ü iade etmek , listenin mevcut olmadığı, boş olmadığı anlamına gelir. Boş bir listeyle birlikte 200'ü geri getirmek bana mantıklı gelen tek seçenek gibi görünüyor.
avakar

1

Sert cevabın işaretli cevap olduğunu sanmıyorum.

Nirth tarafından verilen cevap, gerçek bir REST senaryosunda en iyisi olmalıdır. Vücut yanıtı boş ve http durum kodu: 204; kaynak var, ancak o sırada "içerik yok" var: boş.

REST HTTP_Status_Codes


1

API'nin tüm istemcileri tarafından ele alınmasını kolaylaştırdığından 200 + boş dizi öneririm. 200 + array "Orada bulunan tüm verileri döndürdüm" anlamına geliyor. Hem verileri sağlayan kod hem de onu işleyen kod için, öğelerin sayısı önemsiz olacaktır.

Diğer tüm durum kodlarının sunucu tarafından doğru bir şekilde belgelenmesi ve uygun bir şekilde sunulması ve müşteri tarafından uygun şekilde işlenmesi gerekir ve bunun ne kadar muhtemel olduğunu hepimiz biliyoruz.

Durum 204 + boş gövdeye geri dönme önerisi vardı. Yani zorlamak anlamına gelir her tek doğru işlem durumu 204 müşteri. Üstelik onları JSON dışı cevapları ele almaya zorladın! Umarım herkes, bir istek bir yanıt aldığından, http kullanıldığında cevabın sunucudan geldiği anlamına gelmediğini ve yanıtın JSON'un bu durumların birçoğunu ele aldığı anlamına geldiğini anlamış olur.


0

Ben "değişir" olur.

Sıfır makul bir sonuçsa boş listeye geri dönün. Örneğin, "bob" olarak adlandırılan tüm çalışanları almak istiyorsanız, "hiçbiri" oldukça makul bir sonuçtur. Beklenen bir sonuç değilse, bir hata döndür. Örneğin, çalıştığınız bir kişi için tarihi bir sokak adresleri listesi alma. Bir yerde yaşamalılar, bu nedenle sonuç normal bir durum değil, bir hata olabilir.

Eminim ki örneğimin özellikleriyle tartışabilirsin, ama fikrin var ...


0
  • Her şeyden önce, getURL’nizde olması RESTful değildir, GET, HTTP yöntemiyle belirtilir.
  • Eğer böyle bir koleksiyon isteğinde bulunuyorsanız GET api/moviesdönüş a 200 OKboş bir dizi [].
  • Gibi belirli bir film istiyorsanız GET api/movies/1( 1kimliği nerede? ) Ve mevcut değilse, a 404 Not Found.

Neden? Kaynak istiyorsun . Koleksiyon talep ederken kaynağın kendisi (koleksiyon) vardır. Bunun için, bir 404yanlış. Ancak, belirli bir film talep ederseniz ve mevcut değilse, istenen kaynak mevcut değildir ve geri dönmek zorundasınız 404.


-2

JSON döndürüyorsanız, her zaman sayım ve hata iletisini ve belki de hata olup olmadığını belirten bir Boolean, her satır listesiyle döndürülen standart üç meta değerimdir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.