วิธีที่ดีที่สุดในการคืนอาเรย์เป็นการตอบกลับใน RESTful API คืออะไร


40

สมมติว่าเรามีทรัพยากรเช่นนี้

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

books:
    type: array
    items: book

ดังนั้นเมื่อมีคนทำGETทรัพยากรหนังสือเราจะคืนสิ่งต่อไปนี้

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

ฉันได้ยินจากคนในที่ทำงานว่าวิธีปฏิบัติที่เหลือแนะนำให้กลับคำตอบเป็นวัตถุ JSON ซึ่งหมายความว่า schema ของเราสำหรับbooksจะมีลักษณะเช่นนี้

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

ดังนั้นตอนนี้การตอบสนองจะมีลักษณะเช่นนี้

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

ข้อใดที่เป็นวิธีปฏิบัติที่ดีที่สุดของ REST


1
JSON RESTful เป็นอย่างไร คุณควรกลับ HTML หรือไม่
Ewan

3
@Ewan: น้ำหนักบรรทุกไม่สำคัญ นั่นคือสิ่งที่ประเภท MIME มีไว้สำหรับ
Robert Harvey

1
ไม่มีแนวปฏิบัติที่ดีที่สุดสำหรับ REST REST สร้างจาก HATEOAS ซึ่งหมายถึงการค้นพบ API ของคุณ ค้นหา HAL หรือ JSON-LD
Florian Margaine

Json-ld: ทำงานช้าลงเรื่อย ๆ ไปยัง WCF
Ewan

จากสิ่งที่ฉันอ่านอาร์เรย์ห่อ JSON ภายในวัตถุเป็นมาตรการป้องกันกับช่องโหว่รายงานในเบราว์เซอร์รุ่นเก่า - haacked.com/archive/2009/06/25/json-hijacking.aspx ดูเหมือนว่าจะได้รับการแก้ไขในเบราว์เซอร์ที่ทันสมัยในปัจจุบัน ปลอดภัยกว่าดีกว่าขออภัยฉันเดาว่า
Gishu

คำตอบ:


35

ในทางปฏิบัติตัวเลือกที่สองคือแนวปฏิบัติที่ดีที่สุด เหตุผลนี้เป็นเพราะคุณไม่สามารถขยายทรัพยากรได้ทั้งหมดเมื่อคุณเพิ่งส่งกลับอาร์เรย์

ตัวอย่างเช่น: หากคุณต้องการเพิ่มจำนวนระเบียนทั้งหมดที่คุณทำไปแล้วด้วยวิธีการอาเรย์เท่านั้น

หากสิ่งนั้นเกิดขึ้นในรายการเดียว API คุณต้องการให้มันสอดคล้องกันดังนั้นทำให้วัตถุทั้งหมดแล้ว API ของคุณจะสอดคล้องกันและง่ายต่อการใช้งานสำหรับนักพัฒนา

ตัวอย่างเช่นสมมติว่านักพัฒนาเขียนรหัสทั่วไปเพื่อใช้ API ของคุณเพื่อแสดงรายการและหน้ารายละเอียด เขาไม่ต้องการสร้างข้อยกเว้นเพราะบางครั้งมันเป็นอาร์เรย์และบางครั้งก็เป็นวัตถุที่มีคุณสมบัติรายการ

คำตอบทั้งหมดนี้ไม่มีอะไรที่ต้องทำกับหลักการเกี่ยวกับการพักผ่อนเกลียดชังและโปรโตคอลอื่น ๆ แต่เป็นเรื่องจริงเกี่ยวกับข้อมูลที่คุณต้องการส่งไปยังลูกค้า หากคุณตัดสินใจที่จะทำตามตัวอย่างเกลียดชังให้ปิดหลักสูตรตามมาตรฐานของพวกเขา (ซึ่งเป็นวัตถุ btw)


3
+1 สำหรับ "การเป็นจริงเกี่ยวกับข้อมูล" (และในขณะที่ยังคงรับรู้ว่ามีคำจำกัดความด้านเทคนิคที่แม่นยำยิ่งขึ้นสำหรับ REST)
ตกลง

8

ทั้งสอง

[{"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"}]
}

ถูกต้อง Json ฉันไม่คิดว่าคุณควรเพิ่ม "list" หากไม่จำเป็นอาจจะสับสนเพราะสิ่งที่ตามมาคืออาร์เรย์แทนที่จะเป็นรายการ

วิธีปฏิบัติที่ดีที่สุด REST? API ควรให้การตอบสนองที่เหมาะสมกับสิ่งที่ตั้งไว้ในส่วนหัวของ Accept และเอกสารที่ดี


7

เหตุผลที่คุณทำให้การตอบสนองของคุณสอดคล้องกับJSON คือ JSON นั้นเป็นมาตรฐานแบบ defacto ภาษาใด ๆ ที่มีโปรแกรมวิเคราะห์คำ JSON สามารถแยกวิเคราะห์ได้เล็กน้อยและถ้าคุณใช้ JavaScript คุณไม่จำเป็นต้องใช้เครื่องมือวิเคราะห์คำเนื่องจาก JavaScript เข้าใจเป็นอย่างดี

กล่าวอีกนัยหนึ่งทำให้เป็นไปตาม JSON และคุณไม่ต้องเขียนโปรแกรมแยกวิเคราะห์ของคุณเอง นอกจากนี้จะไม่มีเรื่องที่น่าประหลาดใจเมื่อนักพัฒนาซอฟต์แวร์รายถัดไปเขียนซอฟต์แวร์ที่สิ้นเปลืองบริการ

REST ไม่มีส่วนเกี่ยวข้องกับสคีมา JSON ของคุณ สคีมาเป็นที่ยอมรับจากมุมมอง REST


9
นั่นเป็นคำตอบของคำถามหรือไม่ ฉันอ่านมันว่า "ฉันควรใช้อาร์เรย์ json หรือวัตถุ json เป็นรูทหรือไม่" ทั้งสองสามารถแยกวิเคราะห์ด้วย json parsers ดังนั้นคำตอบของคุณไม่ช่วยให้พวกเขาตัดสินใจ
CodesInChaos

งั้นมันก็ไม่สำคัญ ฉันอัพเดตคำตอบแล้ว
Robert Harvey

หากเรากำลังพูดถึง REST สคีมาไม่สำคัญตราบใดที่มันสามารถให้การควบคุมสื่อหลายมิติสำหรับการค้นพบและการจัดการทรัพยากรเพิ่มเติมตามการตอบสนองเพียงอย่างเดียวและไม่มีข้อมูลนอกวงอื่น ๆ ... ซึ่ง ไม่มีรูปแบบใดที่ OP กล่าวถึงดูเหมือนจะทำ
toniedzwiedz

...and if you're using JavaScript, you don't even need a parser since JavaScript understands it natively.ก็ใช่และไม่ใช่ JSON เป็นส่วนหนึ่งของ JavaScript แต่เรียกevalแทนการใช้ parser ทันทีทำให้คุณเสี่ยงต่อการ "JSON" ที่มีรหัสที่เป็นอันตรายและการแยกเป็นส่วนใหญ่มักเป็นวิธีที่มีประสิทธิภาพมากขึ้นกว่าevalนะ
Doval

5

พจนานุกรมที่มี "รายการ" คีย์เดียวที่ไม่มีความหมายและค่าอาร์เรย์ไม่มีจุดหมาย - ส่งคืนอาร์เรย์แทน

หากบริการเดียวกันสามารถส่งคืนหนังสือซีดีหรือดีวีดีคุณสามารถส่งคืนพจนานุกรมด้วยคีย์ "books" และค่าอาร์เรย์ อาจมีคีย์ "ดีวีดี" อีกชุดที่มีชุดดีวีดีมากมาย ตัวอย่างเช่นหากลูกค้าสามารถสอบถามรายการซื้อทั้งหมดของพวกเขา

หากคุณมั่นใจว่าคำตอบจะถูกตีความเป็นรายการหนังสือเท่านั้น (หากคำขอบอกว่า "ให้รายชื่อหนังสือ") จากนั้นอาร์เรย์ก็ใช้ได้


5

ตัวเลือกที่สองเป็นวิธีที่ต้องการด้วยเหตุผลด้านความปลอดภัย เบราว์เซอร์รุ่นเก่ามีช่องโหว่ด้านความปลอดภัยที่อนุญาตให้ใช้รหัส javascript อื่น ๆ ในหน้าเว็บเพื่อขโมยข้อมูลของคุณหากมีการส่งคืนเป็นอาร์เรย์ JSON ดังนั้นวิธีปฏิบัติที่ดีที่สุดในอดีตคือไม่ส่งคืนอาร์เรย์ JSON ในความเป็นจริงมีกรอบบางส่วนที่มีฟังก์ชั่น "json-ify" เลือกตัวเลือก 2 โดยค่าเริ่มต้นเมื่อคุณผ่านในอาร์เรย์

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

ทั้งสองเป็น json และเป็นไปตาม REST ฉันจะทำให้การตอบสนองมีรายละเอียดมากขึ้นในรายการเปลี่ยนแปลงกรณีของคุณเป็นหนังสือ หรืออะไรทำนองนี้:

{ "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"}
    ]

}}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.