Cách tốt nhất để trả về một mảng như một phản hồi trong API RESTful là gì?


40

Giả sử chúng ta có tài nguyên như thế này,

book:
    type: object
    properties:
        author: {type: string}
        isbn: {type: string}
        title: {type: string}

books:
    type: array
    items: book

Vì vậy, khi ai đó tạo GETtài nguyên trên sách, chúng tôi sẽ trả lại như sau

[{"author": "Dan Brown", "isbn": "123456", "title": "Digital Fortress"},
 {"author": "JK Rowling", "isbn": "234567", "title": "Harry Potter and the Chamber of Secrets"}]

Tôi đã nghe từ một người nào đó tại nơi làm việc rằng thực tiễn REST được đề xuất là luôn trả về các phản hồi dưới dạng các đối tượng JSON, điều đó có nghĩa là lược đồ của chúng ta bookssẽ trông như thế này,

books:
    type: object
    properties:
        list:
            type: array
            items: book

Vì vậy, bây giờ, phản ứng sẽ như thế này,

{
    "list": [{"author": "Dan Brown", "isbn": "123456", "title": "Digital Fortress"},
             {"author": "JK Rowling", "isbn": "234567", "title": "Harry Potter and the Chamber of Secrets"}]
}

Cái nào trong số này là thực hành REST tốt nhất?


1
JSON RESTful là gì? Bạn có nên trả lại html không?
Ewan

3
@Ewan: Tải trọng không thành vấn đề. Đó là những gì MIME dành cho.
Robert Harvey

1
Không phải là thực hành tốt nhất cho REST. REST được tạo từ HATEOAS, có nghĩa là khả năng khám phá API của bạn. Tra cứu HAL hoặc JSON-LD.
Florian Margaine

Json-ld: làm việc chậm chạp về phía WCF
Ewan

Từ những gì tôi đọc được, bao gồm các mảng JSON bên trong một đối tượng là một biện pháp phòng thủ chống lại lỗ hổng được báo cáo trong các trình duyệt cũ hơn - haacked.com/archive/2009/06/25/json-hijacking.aspx . Điều này dường như đã được cố định trong các trình duyệt hiện đại ngày nay. An toàn hơn là xin lỗi tôi đoán ..
Gishu

Câu trả lời:


35

Trong thực tế lựa chọn thứ hai là thực hành tốt nhất. Lý do cho điều này là bạn hoàn toàn không thể mở rộng tài nguyên khi bạn chỉ trả về một mảng.

Ví dụ: Nếu bạn cần thêm số lượng tất cả các bản ghi bạn đã thực hiện với phương pháp chỉ mảng.

Nếu điều đó xảy ra trong một danh sách api thì bạn muốn giữ nó nhất quán để làm cho tất cả một đối tượng thì api của bạn trở nên nhất quán hơn và dễ sử dụng hơn cho các nhà phát triển.

Ví dụ: giả sử nhà phát triển viết mã chung để sử dụng api của bạn để hiển thị danh sách và các trang chi tiết. Anh ta không muốn xây dựng một ngoại lệ vì đôi khi nó là một mảng và đôi khi nó là một đối tượng có thuộc tính danh sách.

Câu trả lời này hoàn toàn không liên quan gì đến các nguyên tắc về nghỉ ngơi, ghét và các giao thức khác mà chỉ là sự thật về dữ liệu bạn cần gửi cho khách hàng. Nếu bạn quyết định làm theo ví dụ như ghét thì tất nhiên hãy tuân theo các tiêu chuẩn của họ (cũng là đối tượng btw).


3
+1 cho "thực tế về dữ liệu" (và trong khi vẫn nhận ra rằng có một định nghĩa kỹ thuật hơn, chính xác hơn cho REST).
tham lam

8

Cả hai

[{"author": "Dan Brown", "isbn": "123456", "title": "Digital Fortress"},{"author": "JK Rowling", "isbn": "234567", "title": "Harry Potter and the Chamber of Secrets"}]

{
    "list": [{"author": "Dan Brown", "isbn": "123456", "title": "Digital Fortress"},
         {"author": "JK Rowling", "isbn": "234567", "title": "Harry Potter and the Chamber of Secrets"}]
}

là Json hợp lệ. Tôi không nghĩ bạn nên thêm "danh sách" nếu không cần thiết, nó thậm chí có thể gây nhầm lẫn bởi vì những gì theo sau nó là một mảng, thay vì một danh sách.

Thực hành REST tốt nhất? API sẽ cung cấp phản hồi thích hợp cho bất kỳ cài đặt nào trong tiêu đề Chấp nhận và tài liệu tốt.


7

Lý do bạn thực hiện phản hồi của mình tuân thủ JSON là JSON là một tiêu chuẩn không chính xác; bất kỳ ngôn ngữ nào có trình phân tích cú pháp JSON đều có thể phân tích cú pháp một cách tầm thường và nếu bạn đang sử dụng JavaScript, bạn thậm chí không cần trình phân tích cú pháp vì JavaScript hiểu nó một cách tự nhiên.

Nói cách khác, làm cho nó tuân thủ JSON và bạn sẽ không phải viết trình phân tích cú pháp của riêng mình. Hơn nữa, sẽ không có gì ngạc nhiên khi nhà phát triển tiếp theo viết phần mềm sử dụng dịch vụ.

REST không có gì để làm với lược đồ JSON của bạn. Hoặc là lược đồ được chấp nhận, từ góc độ REST.


9
Điều đó có trả lời câu hỏi không? Tôi đọc nó là "Tôi nên sử dụng một mảng json hoặc một đối tượng json làm root?". Cả hai có thể được phân tích cú pháp bằng trình phân tích cú pháp json, vì vậy câu trả lời của bạn không giúp họ quyết định.
CodeInChaos

Sau đó, nó không thành vấn đề. Tôi đã cập nhật câu trả lời của mình.
Robert Harvey

Nếu chúng ta đang nói về REST, lược đồ không quan trọng miễn là nó có khả năng cung cấp các điều khiển hypermedia để khám phá và thao túng các tài nguyên tiếp theo chỉ dựa trên phản hồi và không có thông tin ngoài luồng nào khác ... không có định dạng nào được đề cập bởi OP dường như làm được.
toniedzwiedz

...and if you're using JavaScript, you don't even need a parser since JavaScript understands it natively.Vâng, có và không. JSON là một tập hợp con của JavaScript nhưng việc gọi evalthay vì sử dụng trình phân tích cú pháp ngay lập tức khiến bạn dễ bị "JSON" chứa mã độc hại và việc phân tích cú pháp rất có thể hiệu quả hơn bất kỳ cách nào eval.
Doval 9/12/2015

5

Một từ điển với một "danh sách" khóa vô nghĩa duy nhất và một giá trị mảng là vô nghĩa - thay vào đó trả về một mảng.

Nếu cùng một dịch vụ có thể trả về sách, CD hoặc DVD, thì bạn có thể trả lại một từ điển với một "sách" chính và một giá trị mảng. Có thể có một "DVD" quan trọng khác với một loạt các DVD. Ví dụ: nếu khách hàng có thể hỏi danh sách tất cả các giao dịch mua của họ.

Nếu bạn chắc chắn rằng phản hồi sẽ chỉ được hiểu là một danh sách các cuốn sách (nếu yêu cầu nói "cho tôi một danh sách các cuốn sách") thì chỉ cần một mảng là ổn.


5

Tùy chọn thứ hai cũng là phương pháp ưa thích vì lý do bảo mật. Các trình duyệt cũ hơn có một lỗ hổng bảo mật cho phép mã javascript khác trên trang web đánh cắp dữ liệu của bạn nếu nó được trả về dưới dạng mảng JSON. Vì vậy, trong lịch sử, cách tốt nhất là không trả về mảng JSON. Trong thực tế, có một số khung có chức năng "json-ify" chọn tùy chọn 2 theo mặc định khi bạn truyền vào một mảng.

https://stackoverflow.com/questions/3503102/what-are-top-level-json-arrays-and-why-are-they-a-security-risk

http://ejohn.org/blog/re-securing-json/


1

cả hai đều là json và tuân thủ REST. Tôi sẽ làm cho câu trả lời mô tả nhiều hơn, trong trường hợp của bạn thay đổi danh sách thành sách. Hoặc thứ gì đó giống thế này :

{ "responceObject" : {

   results : 2,

    "Books": [
        {"author": "Dan Brown", "isbn": "123456", "title": "Digital Fortress"},
        {"author": "JK Rowling", "isbn": "234567", "title": "Harry Potter and the Chamber of Secrets"}
    ]

}}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.