เอกสารนี้อธิบายเทคนิคบางประการที่คุณสามารถใช้เพื่อปรับปรุงประสิทธิภาพของแอปพลิเคชันของคุณ ในบางกรณี ตัวอย่างจาก API อื่นๆ หรือ API ทั่วไปจะใช้เพื่อแสดงให้เห็นภาพของแนวคิดที่นำเสนอ อย่างไรก็ตาม Google Wallet API ก็ใช้แนวคิดเดียวกันนี้ได้เช่นกัน
การบีบอัดโดยใช้ gzip
วิธีที่ง่ายและสะดวกในการลดแบนด์วิดท์ที่ต้องใช้สำหรับแต่ละคำขอคือการเปิดใช้การบีบอัด gzip แม้ว่าการดำเนินการนี้จะต้องใช้เวลา CPU เพิ่มเติมในการคลายการบีบอัดผลลัพธ์ แต่การแลกกับค่าใช้จ่ายของเครือข่ายมักทำให้คุ้มค่ามาก
เพื่อให้ได้รับการตอบสนองที่เข้ารหัสด้วย gzip คุณต้องทำ 2 อย่าง ได้แก่ ตั้งค่าส่วนหัว Accept-Encoding
และแก้ไข User Agent ให้มีสตริง gzip
ต่อไปนี้คือตัวอย่างของส่วนหัว HTTP ที่มีรูปแบบถูกต้องสำหรับการเปิดใช้การบีบอัด gzip
Accept-Encoding: gzip User-Agent: my program (gzip)
การทํางานกับทรัพยากรบางส่วน
อีกวิธีหนึ่งในการปรับปรุงประสิทธิภาพการเรียก API ของคุณคือการส่งและรับเฉพาะข้อมูลส่วนที่คุณสนใจเท่านั้น ซึ่งจะช่วยให้แอปพลิเคชันของคุณหลีกเลี่ยงการโอน แยกวิเคราะห์ และจัดเก็บช่องที่ไม่จำเป็น ทำให้สามารถใช้ทรัพยากร เช่น เครือข่าย, CPU และหน่วยความจำได้อย่างมีประสิทธิภาพมากขึ้น
คำขอบางส่วนมี 2 ประเภท ได้แก่
- การตอบกลับบางส่วน: คำขอที่คุณระบุช่องที่จะรวมไว้ในการตอบกลับ (ใช้พารามิเตอร์คำขอ
fields
) - แพตช์: คำขออัปเดตที่คุณส่งเฉพาะช่องที่ต้องการเปลี่ยน (ใช้คำกริยา HTTP
PATCH
)
ดูรายละเอียดเพิ่มเติมเกี่ยวกับการสร้างคำขอบางส่วนในหัวข้อต่อไปนี้
คำตอบบางส่วน
โดยค่าเริ่มต้น เซิร์ฟเวอร์จะส่งข้อมูลแทนทรัพยากรทั้งหมดกลับมาหลังจากประมวลผลคำขอ เพื่อประสิทธิภาพที่ดีขึ้น คุณขอให้เซิร์ฟเวอร์ส่งเฉพาะช่องที่จำเป็นจริงๆ และรับการตอบกลับบางส่วนแทนได้
หากต้องการขอการตอบกลับบางส่วน ให้ใช้พารามิเตอร์คำขอ fields
เพื่อระบุช่องที่ต้องการให้แสดงผล คุณใช้พารามิเตอร์นี้กับคำขอใดก็ได้ที่แสดงข้อมูลการตอบกลับ
โปรดทราบว่าพารามิเตอร์ fields
จะส่งผลต่อข้อมูลการตอบกลับเท่านั้น โดยจะไม่ส่งผลต่อข้อมูลที่คุณต้องการส่ง (หากมี) หากต้องการลดปริมาณข้อมูลที่ส่งเมื่อแก้ไขทรัพยากร ให้ใช้คำขอแพตช์
ตัวอย่าง
ตัวอย่างต่อไปนี้แสดงการใช้พารามิเตอร์ fields
กับ API "Demo" ทั่วไป (สมมติ)
คำขอแบบง่าย: คำขอ HTTP GET
นี้จะข้ามพารามิเตอร์ fields
และส่งคืนทรัพยากรทั้งหมด
https://www.googleapis.com/demo/v1
การตอบกลับแหล่งข้อมูลเต็มรูปแบบ: ข้อมูลทรัพยากรทั้งหมดจะมีช่องต่อไปนี้ รวมถึงช่องอื่นๆ อีกหลายรายการที่ละเว้นเพื่อความสั้นกระชับ
{ "kind": "demo", ... "items": [ { "title": "First title", "comment": "First comment.", "characteristics": { "length": "short", "accuracy": "high", "followers": ["Jo", "Will"], }, "status": "active", ... }, { "title": "Second title", "comment": "Second comment.", "characteristics": { "length": "long", "accuracy": "medium" "followers": [ ], }, "status": "pending", ... }, ... ] }
คำขอตอบกลับบางส่วน: คำขอต่อไปนี้สำหรับทรัพยากรเดียวกันนี้ใช้พารามิเตอร์ fields
เพื่อลดจำนวนข้อมูลที่แสดงผลลงอย่างมาก
https://www.googleapis.com/demo/v1?fields=kind,items(title,characteristics/length)
การตอบกลับบางส่วน: ในการตอบสนองต่อคำขอข้างต้น เซิร์ฟเวอร์จะส่งการตอบกลับที่มีเฉพาะข้อมูลชนิดกลับมาพร้อมกับอาร์เรย์รายการข้อมูลที่ปรับลง ซึ่งจะมีเฉพาะชื่อ HTML และข้อมูลลักษณะเฉพาะความยาวในแต่ละรายการ
200 OK
{ "kind": "demo", "items": [{ "title": "First title", "characteristics": { "length": "short" } }, { "title": "Second title", "characteristics": { "length": "long" } }, ... ] }
โปรดทราบว่าการตอบกลับจะเป็นออบเจ็กต์ JSON ที่มีเฉพาะช่องที่เลือกและออบเจ็กต์ระดับบนสุดที่ล้อมรอบอยู่
เราจะกล่าวถึงรายละเอียดเกี่ยวกับวิธีจัดรูปแบบพารามิเตอร์ fields
ในขั้นตอนถัดไป ตามด้วยรายละเอียดเพิ่มเติมเกี่ยวกับสิ่งที่แสดงผลในคำตอบ
สรุปไวยากรณ์ของพารามิเตอร์ของช่อง
รูปแบบของค่าพารามิเตอร์คำขอ fields
อิงตามไวยากรณ์ XPath อย่างคร่าวๆ ดูสรุปไวยากรณ์ที่รองรับได้ที่ด้านล่าง และดูตัวอย่างเพิ่มเติมในส่วนต่อไปนี้
- ใช้รายการที่คั่นด้วยเครื่องหมายจุลภาคเพื่อเลือกหลายช่อง
- ใช้
a/b
เพื่อเลือกช่องb
ที่ฝังอยู่ในช่องa
และใช้a/b/c
เพื่อเลือกช่องc
ที่ฝังอยู่ภายในb
ข้อยกเว้น: สำหรับการตอบกลับจาก API ที่ใช้ Wrapper "ข้อมูล" ซึ่งการตอบกลับฝังอยู่ในออบเจ็กต์
data
ที่มีลักษณะคล้ายdata: { ... }
โปรดอย่าใส่ "data
" ในข้อกำหนดของfields
การรวมออบเจ็กต์ข้อมูลด้วยข้อกำหนดเฉพาะของช่อง เช่นdata/a/b
จะทำให้เกิดข้อผิดพลาด แต่ให้ใช้เพียงข้อมูลจำเพาะของfields
เช่นa/b
- ใช้ตัวเลือกย่อยเพื่อขอชุดฟิลด์ย่อยที่เฉพาะเจาะจงของอาร์เรย์หรือออบเจ็กต์ โดยวางนิพจน์ในวงเล็บ "
( )
"เช่น
fields=items(id,author/email)
จะแสดงเฉพาะรหัสรายการและอีเมลผู้เขียนสำหรับแต่ละองค์ประกอบในอาร์เรย์ items หรือจะระบุช่องย่อยช่องเดียวก็ได้ โดยที่fields=items(id)
เทียบเท่ากับfields=items/id
- ใช้ไวลด์การ์ดในการเลือกช่อง หากจำเป็น
เช่น
fields=items/pagemap/*
เลือกออบเจ็กต์ทั้งหมดใน Pagemap
ตัวอย่างเพิ่มเติมเกี่ยวกับการใช้พารามิเตอร์ฟิลด์
ตัวอย่างด้านล่างมีคำอธิบายว่าค่าพารามิเตอร์ fields
ส่งผลต่อการตอบกลับอย่างไร
หมายเหตุ: ค่าพารามิเตอร์การค้นหา fields
ต้องเป็น URL ที่เข้ารหัส เช่นเดียวกับค่าพารามิเตอร์การค้นหาทั้งหมด ตัวอย่างในเอกสารนี้จะละเว้นการเข้ารหัสเพื่อให้อ่านง่ายขึ้น
- ระบุช่องที่คุณต้องการให้แสดงผล หรือเลือกช่อง
- ค่าพารามิเตอร์ของคำขอ
fields
เป็นรายการที่คั่นด้วยคอมมา และระบุแต่ละช่องโดยสัมพันธ์กับรูทของการตอบกลับ ดังนั้น หากคุณกําลังดําเนินการรายการ คําตอบจะเป็นคอลเล็กชัน และโดยทั่วไปจะมีอาร์เรย์ทรัพยากร หากคุณกำลังดำเนินการที่แสดงผลทรัพยากรเดียว ระบบจะระบุฟิลด์ให้สัมพันธ์กับทรัพยากรนั้น หากช่องที่คุณเลือกคือ (หรือเป็นส่วนหนึ่งของ) อาร์เรย์ เซิร์ฟเวอร์จะแสดงผลส่วนที่เลือกขององค์ประกอบทั้งหมดในอาร์เรย์
ตัวอย่างระดับคอลเล็กชันบางส่วนมีดังนี้
ตัวอย่าง ผลกระทบ items
แสดงผลองค์ประกอบทั้งหมดในอาร์เรย์ items รวมถึงช่องทั้งหมดในแต่ละองค์ประกอบ แต่ไม่รวมช่องอื่นๆ etag,items
แสดงผลทั้งช่อง etag
และองค์ประกอบทั้งหมดในอาร์เรย์ itemsitems/title
แสดงเฉพาะช่อง title
สำหรับองค์ประกอบทั้งหมดในอาร์เรย์ items
เมื่อใดก็ตามที่ระบบแสดงผลช่องที่ซ้อนกัน การตอบสนองจะรวมออบเจ็กต์ระดับบนสุดที่ล้อมรอบอยู่ ช่องหลักจะไม่รวมช่องย่อยอื่นๆ เว้นแต่จะเลือกไว้อย่างชัดแจ้งcontext/facets/label
แสดงเฉพาะช่อง label
สำหรับสมาชิกทั้งหมดของอาร์เรย์facets
ซึ่งฝังอยู่ใต้ออบเจ็กต์context
items/pagemap/*/title
สำหรับแต่ละองค์ประกอบในอาร์เรย์ items จะแสดงเฉพาะช่อง title
(หากมี) ของออบเจ็กต์ทั้งหมดที่เป็นรายการย่อยของpagemap
ตัวอย่างระดับทรัพยากรบางส่วนมีดังนี้
ตัวอย่าง ผลกระทบ title
แสดงฟิลด์ title
ของทรัพยากรที่ขอauthor/uri
แสดงผลฟิลด์ย่อย uri
ของออบเจ็กต์author
ในทรัพยากรที่ขอlinks/*/href
แสดงผลฟิลด์ href
ของออบเจ็กต์ทั้งหมดที่เป็นรายการย่อยของlinks
- ขอเฉพาะบางส่วนของช่องที่เจาะจงโดยใช้การเลือกย่อย
- โดยค่าเริ่มต้น หากคำขอระบุช่องที่เจาะจง เซิร์ฟเวอร์จะแสดงออบเจ็กต์หรือองค์ประกอบอาร์เรย์ทั้งหมด คุณสามารถระบุการตอบกลับที่มีเฉพาะฟิลด์ย่อยบางช่องได้ ซึ่งคุณสามารถทำได้โดยใช้ไวยากรณ์การเลือกย่อย "
( )
" ดังที่แสดงในตัวอย่างด้านล่างตัวอย่าง ผลกระทบ items(title,author/uri)
แสดงเฉพาะค่าของ title
และuri
ของผู้เขียนสำหรับแต่ละองค์ประกอบในอาร์เรย์ items
การจัดการคำตอบบางส่วน
หลังจากเซิร์ฟเวอร์ประมวลผลคำขอที่ถูกต้องซึ่งมีพารามิเตอร์การค้นหา fields
แล้ว เซิร์ฟเวอร์จะส่งรหัสสถานะ HTTP 200 OK
กลับมาพร้อมข้อมูลที่ขอ หากพารามิเตอร์การค้นหา fields
มีข้อผิดพลาดหรือไม่ถูกต้อง เซิร์ฟเวอร์จะแสดงรหัสสถานะ HTTP 400 Bad Request
พร้อมข้อความแสดงข้อผิดพลาดที่บอกให้ผู้ใช้ทราบว่าเลือกช่องของตนมีปัญหาอะไร (เช่น "Invalid field selection a/b"
)
นี่คือตัวอย่างการตอบกลับบางส่วนที่แสดงในส่วนแนะนำด้านบน คำขอดังกล่าวใช้พารามิเตอร์ fields
เพื่อระบุช่องที่จะแสดง
https://www.googleapis.com/demo/v1?fields=kind,items(title,characteristics/length)
การตอบกลับบางส่วนจะมีลักษณะดังนี้
200 OK
{ "kind": "demo", "items": [{ "title": "First title", "characteristics": { "length": "short" } }, { "title": "Second title", "characteristics": { "length": "long" } }, ... ] }
หมายเหตุ: สำหรับ API ที่รองรับพารามิเตอร์การค้นหาสำหรับการใส่เลขหน้าข้อมูล (เช่น maxResults
และ nextPageToken
) ให้ใช้พารามิเตอร์เหล่านั้นเพื่อลดผลลัพธ์ของการค้นหาแต่ละรายการให้เป็นขนาดที่จัดการได้ มิฉะนั้น ประสิทธิภาพที่ได้รับอาจเพิ่มขึ้นจากการตอบสนองบางส่วนอาจไม่รับรู้
แพตช์ (อัปเดตบางส่วน)
นอกจากนี้ คุณยังหลีกเลี่ยงการส่งข้อมูลที่ไม่จำเป็นเมื่อแก้ไขทรัพยากรได้ด้วย หากต้องการส่งข้อมูลที่อัปเดตแล้วเฉพาะสำหรับฟิลด์ที่คุณจะทำการเปลี่ยนแปลง ให้ใช้คำกริยา HTTP PATCH
อรรถศาสตร์ของแพตช์ที่อธิบายในเอกสารนี้แตกต่างจากเดิม (และง่ายกว่า) สำหรับการติดตั้งใช้งาน GData เดิมของการอัปเดตบางส่วน
ตัวอย่างสั้นๆ ด้านล่างแสดงให้เห็นว่าการใช้แพตช์จะลดข้อมูลที่ต้องส่งเพื่อทำการอัปเดตเล็กๆ น้อยๆ ได้อย่างไร
ตัวอย่าง
ตัวอย่างนี้แสดงคำขอแพตช์แบบง่ายๆ เพื่ออัปเดตเฉพาะชื่อของทรัพยากร API "การสาธิต" ทั่วไป (สมมติ) ทรัพยากรยังมีความคิดเห็น ชุดลักษณะ สถานะ และฟิลด์อื่นๆ อีกมากมาย แต่คำขอนี้จะส่งเฉพาะฟิลด์ title
เท่านั้น เนื่องจากเป็นฟิลด์เดียวที่มีการแก้ไข:
PATCH https://www.googleapis.com/demo/v1/324 Authorization: Bearer your_auth_token Content-Type: application/json { "title": "New title" }
คำตอบ:
200 OK
{ "title": "New title", "comment": "First comment.", "characteristics": { "length": "short", "accuracy": "high", "followers": ["Jo", "Will"], }, "status": "active", ... }
เซิร์ฟเวอร์แสดงผลรหัสสถานะ 200 OK
พร้อมการแสดงทรัพยากรที่อัปเดตทั้งหมด เนื่องจากมีเพียงช่อง title
ที่รวมอยู่ในคำขอแพตช์ ค่าดังกล่าวจึงเป็นค่าเดียวที่แตกต่างจากก่อนหน้านี้
หมายเหตุ: หากใช้พารามิเตอร์ fields
ของการตอบกลับบางส่วนร่วมกับแพตช์ คุณจะเพิ่มประสิทธิภาพของคำขออัปเดตได้มากยิ่งขึ้น คำขอแพตช์จะลดขนาดคำขอเท่านั้น การตอบกลับบางส่วนจะลดขนาดคำตอบ ดังนั้นหากต้องการลดปริมาณข้อมูลที่ส่งไปทั้ง 2 ทาง ให้ใช้คำขอแพตช์ที่มีพารามิเตอร์ fields
ความหมายของคำขอแพตช์
เนื้อหาของคำขอแพตช์จะมีเฉพาะช่องทรัพยากรที่คุณต้องการแก้ไข เมื่อระบุช่อง คุณต้องรวมออบเจ็กต์หลักที่ล้อมรอบอยู่ เพื่อให้ออบเจ็กต์หลักที่ล้อมรอบอยู่แสดงผลโดยมีการตอบกลับบางส่วน ข้อมูลที่แก้ไขแล้วที่คุณส่งจะรวมเข้ากับข้อมูลของออบเจ็กต์หลัก หากมี
- เพิ่ม: หากต้องการเพิ่มช่องที่ยังไม่มีอยู่ ให้ระบุช่องใหม่และค่า
- แก้ไข: หากต้องการเปลี่ยนค่าของช่องที่มีอยู่ ให้ระบุช่องดังกล่าวและตั้งค่าเป็นค่าใหม่
- ลบ: หากต้องการลบช่อง ให้ระบุช่องนั้นและตั้งค่าเป็น
null
เช่น"comment": null
นอกจากนี้ยังลบออบเจ็กต์ทั้งหมดได้ (หากเปลี่ยนแปลงไม่ได้) โดยตั้งค่าเป็นnull
หากใช้ไลบรารีของไคลเอ็นต์ Java API ให้ใช้Data.NULL_STRING
แทน โปรดดูรายละเอียดที่ JSON null
หมายเหตุเกี่ยวกับอาร์เรย์: แพตช์คำขอที่มีอาร์เรย์จะแทนที่อาร์เรย์ที่มีอยู่ด้วยอาร์เรย์ที่คุณระบุ คุณไม่สามารถแก้ไข เพิ่ม หรือลบรายการในอาร์เรย์แบบเป็นส่วนๆ ได้
การใช้แพตช์ในรอบอ่าน-แก้ไข-เขียน
แนวทางปฏิบัติที่มีประโยชน์อาจเริ่มด้วยการดึงข้อมูลคำตอบบางส่วนที่มีข้อมูลที่คุณต้องการแก้ไข กระบวนการนี้สำคัญอย่างยิ่งสำหรับทรัพยากรที่ใช้ ETag เนื่องจากคุณต้องระบุค่า ETag ปัจจุบันในส่วนหัว HTTP ของ If-Match
เพื่ออัปเดตทรัพยากรให้สำเร็จ หลังจากได้รับข้อมูลแล้ว คุณจะแก้ไขค่าที่ต้องการเปลี่ยนและส่งตัวแทนบางส่วนที่แก้ไขแล้วกลับไปพร้อมคำขอแพตช์ได้ ต่อไปนี้เป็นตัวอย่างที่ถือว่าทรัพยากรเดโมใช้ ETag
GET https://www.googleapis.com/demo/v1/324?fields=etag,title,comment,characteristics Authorization: Bearer your_auth_token
นี่คือคำตอบบางส่วน
200 OK
{ "etag": "ETagString" "title": "New title" "comment": "First comment.", "characteristics": { "length": "short", "level": "5", "followers": ["Jo", "Will"], } }
คำขอแพตช์ต่อไปนี้อิงตามการตอบกลับดังกล่าว ดังที่แสดงด้านล่าง การทดสอบยังใช้พารามิเตอร์ fields
เพื่อจำกัดข้อมูลที่แสดงผลในการตอบกลับแพตช์ด้วย
PATCH https://www.googleapis.com/demo/v1/324?fields=etag,title,comment,characteristics Authorization: Bearer your_auth_token Content-Type: application/json If-Match: "ETagString"
{ "etag": "ETagString" "title": "", /* Clear the value of the title by setting it to the empty string. */ "comment": null, /* Delete the comment by replacing its value with null. */ "characteristics": { "length": "short", "level": "10", /* Modify the level value. */ "followers": ["Jo", "Liz"], /* Replace the followers array to delete Will and add Liz. */ "accuracy": "high" /* Add a new characteristic. */ }, }
เซิร์ฟเวอร์ตอบสนองด้วยรหัสสถานะ HTTP 200 OK และการนำเสนอบางส่วนของทรัพยากรที่อัปเดตดังนี้
200 OK
{ "etag": "newETagString" "title": "", /* Title is cleared; deleted comment field is missing. */ "characteristics": { "length": "short", "level": "10", /* Value is updated.*/ "followers": ["Jo" "Liz"], /* New follower Liz is present; deleted Will is missing. */ "accuracy": "high" /* New characteristic is present. */ } }
การสร้างคำขอแพตช์โดยตรง
สำหรับคำขอแพตช์บางรายการ คุณต้องอิงตามข้อมูลที่เคยดึงมาก่อนหน้านี้ ตัวอย่างเช่น หากต้องการเพิ่มรายการลงในอาร์เรย์และไม่ต้องการสูญเสียองค์ประกอบอาร์เรย์ที่มีอยู่ คุณต้องรับข้อมูลที่มีอยู่ก่อน ในทำนองเดียวกัน หาก API ใช้ ETag คุณต้องส่งค่า ETag ก่อนหน้าไปพร้อมกับคำขอเพื่อให้อัปเดตทรัพยากรได้สำเร็จ
หมายเหตุ: คุณใช้ส่วนหัว HTTP ของ "If-Match: *"
เพื่อบังคับให้แพตช์ทำงานต่อได้เมื่อใช้ ETag อยู่ หากทำเช่นนี้ ก็ไม่จำเป็นต้องอ่านก่อนเขียน
อย่างไรก็ตาม สำหรับสถานการณ์อื่นๆ คุณสร้างคำขอแพตช์ได้โดยตรง โดยไม่ต้องเรียกข้อมูลที่มีอยู่ก่อน ตัวอย่างเช่น คุณจะตั้งค่าคำขอแพตช์ที่อัปเดตช่องเป็นค่าใหม่หรือเพิ่มช่องใหม่ได้อย่างง่ายดาย มีตัวอย่างดังต่อไปนี้
PATCH https://www.googleapis.com/demo/v1/324?fields=comment,characteristics Authorization: Bearer your_auth_token Content-Type: application/json { "comment": "A new comment", "characteristics": { "volume": "loud", "accuracy": null } }
เมื่อใช้คำขอนี้ หากช่องความคิดเห็นมีค่าที่มีอยู่แล้ว ค่าใหม่จะแทนที่ค่าเดิม ไม่เช่นนั้นระบบจะตั้งค่าเป็นค่าใหม่ ในทำนองเดียวกัน หากมีลักษณะของปริมาณ ค่าจะถูกเขียนทับ หากไม่มี จะเป็นการสร้างค่า ช่องความแม่นยำ (หากมี) จะถูกนำออก
การจัดการการตอบสนองของแพตช์
หลังจากประมวลผลคำขอแพตช์ที่ถูกต้องแล้ว API จะแสดงผลรหัสการตอบกลับ 200 OK
HTTP พร้อมกับการแสดงทรัพยากรที่แก้ไขแล้วอย่างสมบูรณ์ หาก API ใช้ ETag เซิร์ฟเวอร์จะอัปเดตค่า ETag เมื่อประมวลผลคำขอแพตช์เรียบร้อยแล้ว เช่นเดียวกับที่ดำเนินการกับ PUT
คำขอแพตช์จะส่งกลับการแสดงทรัพยากรทั้งหมด เว้นแต่คุณจะใช้พารามิเตอร์ fields
เพื่อลดปริมาณข้อมูลที่แสดงผล
หากคำขอแพตช์ทำให้เกิดสถานะทรัพยากรใหม่ที่ไม่ถูกต้องตามหลักไวยากรณ์หรือเชิงความหมาย เซิร์ฟเวอร์จะแสดงผลรหัสสถานะ HTTP 400 Bad Request
หรือ 422 Unprocessable Entity
และสถานะทรัพยากรจะไม่มีการเปลี่ยนแปลง เช่น หากคุณพยายามลบค่าสำหรับช่องที่ต้องกรอก เซิร์ฟเวอร์จะแสดงข้อผิดพลาด
สัญลักษณ์สำรองเมื่อระบบไม่รองรับคำกริยา Patch HTTP
หากไฟร์วอลล์ของคุณไม่อนุญาตคำขอ HTTP PATCH
ให้ส่งคำขอ HTTP POST
และตั้งค่าส่วนหัวการลบล้างเป็น PATCH
ดังที่แสดงด้านล่าง
POST https://www.googleapis.com/... X-HTTP-Method-Override: PATCH ...
ความแตกต่างระหว่างแพตช์และการอัปเดต
ในทางปฏิบัติ เมื่อส่งข้อมูลสำหรับคำขออัปเดตที่ใช้กริยา HTTP PUT
คุณเพียงต้องส่งเพียงช่องที่จำเป็นหรือไม่บังคับ ส่วนในกรณีที่คุณส่งค่าสำหรับช่องที่เซิร์ฟเวอร์กำหนด ระบบจะไม่สนใจค่าเหล่านั้น การอัปเดตนี้อาจดูเป็นอีกวิธีหนึ่งในการอัปเดตเพียงบางส่วน แต่วิธีนี้มีข้อจำกัดบางประการ ในการอัปเดตที่ใช้คำกริยา HTTP PUT
คำขอจะไม่สำเร็จหากคุณไม่ใส่พารามิเตอร์ที่จำเป็น และจะล้างข้อมูลที่ตั้งค่าไว้ก่อนหน้านี้หากคุณไม่ได้ระบุพารามิเตอร์ที่ไม่บังคับ
การใช้แพตช์จะปลอดภัยกว่ามากด้วยเหตุผลนี้ คุณจะให้ข้อมูลแก่ช่องที่ต้องการเปลี่ยนแปลงเท่านั้น ระบบจะไม่ล้างช่องที่คุณละเว้น ข้อยกเว้นเพียงอย่างเดียวของกฎนี้จะเกิดขึ้นกับองค์ประกอบหรืออาร์เรย์ที่ซ้ำกัน กล่าวคือ หากคุณยกเว้นองค์ประกอบหรืออาร์เรย์ทั้งหมด องค์ประกอบหรืออาร์เรย์ทั้งหมดจะยังคงเดิม หากคุณระบุรายการใดรายการหนึ่ง ชุดทั้งชุดจะถูกแทนที่ด้วยชุดที่คุณระบุ
คำขอแบบกลุ่มไปยัง Google Wallet
Google Wallet API รองรับการเรียก API แบบกลุ่มเข้าด้วยกันเพื่อลดจำนวนการเชื่อมต่อที่ไคลเอ็นต์ต้องสร้าง ดูข้อมูลเพิ่มเติมเกี่ยวกับคำขอแบบกลุ่มและโครงสร้างการตอบกลับได้ที่รายละเอียดกลุ่ม
โค้ดตัวอย่างต่อไปนี้แสดงคำขอแบบกลุ่ม ตัวอย่าง Java และ PHP ใช้ไลบรารี Google Wallet เพื่อลดความซับซ้อนในการสร้างคลาสและออบเจ็กต์
Java
หากต้องการเริ่มการผสานรวมใน Java โปรดดู ตัวอย่างโค้ดทั้งหมดบน GitHub
/** * Batch create Google Wallet objects from an existing class. * * @param issuerId The issuer ID being used for this request. * @param classSuffix Developer-defined unique ID for this pass class. */ public void BatchCreateObjects(String issuerId, String classSuffix) throws IOException { // Create the batch request client BatchRequest batch = service.batch(new HttpCredentialsAdapter(credentials)); // The callback will be invoked for each request in the batch JsonBatchCallback<LoyaltyObject> callback = new JsonBatchCallback<LoyaltyObject>() { // Invoked if the request was successful public void onSuccess(LoyaltyObject response, HttpHeaders responseHeaders) { System.out.println("Batch insert response"); System.out.println(response.toString()); } // Invoked if the request failed public void onFailure(GoogleJsonError e, HttpHeaders responseHeaders) { System.out.println("Error Message: " + e.getMessage()); } }; // Example: Generate three new pass objects for (int i = 0; i < 3; i++) { // Generate a random object suffix String objectSuffix = UUID.randomUUID().toString().replaceAll("[^\\w.-]", "_"); // See link below for more information on required properties // https://developers.google.com/wallet/retail/loyalty-cards/rest/v1/loyaltyobject LoyaltyObject batchObject = new LoyaltyObject() .setId(String.format("%s.%s", issuerId, objectSuffix)) .setClassId(String.format("%s.%s", issuerId, classSuffix)) .setState("ACTIVE") .setHeroImage( new Image() .setSourceUri( new ImageUri() .setUri( "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg")) .setContentDescription( new LocalizedString() .setDefaultValue( new TranslatedString() .setLanguage("en-US") .setValue("Hero image description")))) .setTextModulesData( List.of( new TextModuleData() .setHeader("Text module header") .setBody("Text module body") .setId("TEXT_MODULE_ID"))) .setLinksModuleData( new LinksModuleData() .setUris( Arrays.asList( new Uri() .setUri("http://maps.google.com/") .setDescription("Link module URI description") .setId("LINK_MODULE_URI_ID"), new Uri() .setUri("tel:6505555555") .setDescription("Link module tel description") .setId("LINK_MODULE_TEL_ID")))) .setImageModulesData( List.of( new ImageModuleData() .setMainImage( new Image() .setSourceUri( new ImageUri() .setUri( "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg")) .setContentDescription( new LocalizedString() .setDefaultValue( new TranslatedString() .setLanguage("en-US") .setValue("Image module description")))) .setId("IMAGE_MODULE_ID"))) .setBarcode(new Barcode().setType("QR_CODE").setValue("QR code value")) .setLocations( List.of( new LatLongPoint() .setLatitude(37.424015499999996) .setLongitude(-122.09259560000001))) .setAccountId("Account ID") .setAccountName("Account name") .setLoyaltyPoints( new LoyaltyPoints() .setLabel("Points") .setBalance(new LoyaltyPointsBalance().setInt(800))); service.loyaltyobject().insert(batchObject).queue(batch, callback); } // Invoke the batch API calls batch.execute(); }
PHP
หากต้องการเริ่มการผสานรวมใน PHP โปรดดู ตัวอย่างโค้ดทั้งหมดบน GitHub
/** * Batch create Google Wallet objects from an existing class. * * @param string $issuerId The issuer ID being used for this request. * @param string $classSuffix Developer-defined unique ID for the pass class. */ public function batchCreateObjects(string $issuerId, string $classSuffix) { // Update the client to enable batch requests $this->client->setUseBatch(true); $batch = $this->service->createBatch(); // Example: Generate three new pass objects for ($i = 0; $i < 3; $i++) { // Generate a random object suffix $objectSuffix = preg_replace('/[^\w.-]/i', '_', uniqid()); // See link below for more information on required properties // https://developers.google.com/wallet/retail/loyalty-cards/rest/v1/loyaltyobject $batchObject = new LoyaltyObject([ 'id' => "{$issuerId}.{$objectSuffix}", 'classId' => "{$issuerId}.{$classSuffix}", 'state' => 'ACTIVE', 'heroImage' => new Image([ 'sourceUri' => new ImageUri([ 'uri' => 'https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg' ]), 'contentDescription' => new LocalizedString([ 'defaultValue' => new TranslatedString([ 'language' => 'en-US', 'value' => 'Hero image description' ]) ]) ]), 'textModulesData' => [ new TextModuleData([ 'header' => 'Text module header', 'body' => 'Text module body', 'id' => 'TEXT_MODULE_ID' ]) ], 'linksModuleData' => new LinksModuleData([ 'uris' => [ new Uri([ 'uri' => 'http://maps.google.com/', 'description' => 'Link module URI description', 'id' => 'LINK_MODULE_URI_ID' ]), new Uri([ 'uri' => 'tel:6505555555', 'description' => 'Link module tel description', 'id' => 'LINK_MODULE_TEL_ID' ]) ] ]), 'imageModulesData' => [ new ImageModuleData([ 'mainImage' => new Image([ 'sourceUri' => new ImageUri([ 'uri' => 'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg' ]), 'contentDescription' => new LocalizedString([ 'defaultValue' => new TranslatedString([ 'language' => 'en-US', 'value' => 'Image module description' ]) ]) ]), 'id' => 'IMAGE_MODULE_ID' ]) ], 'barcode' => new Barcode([ 'type' => 'QR_CODE', 'value' => 'QR code value' ]), 'locations' => [ new LatLongPoint([ 'latitude' => 37.424015499999996, 'longitude' => -122.09259560000001 ]) ], 'accountId' => 'Account ID', 'accountName' => 'Account name', 'loyaltyPoints' => new LoyaltyPoints([ 'balance' => new LoyaltyPointsBalance([ 'int' => 800 ]) ]) ]); $batch->add($this->service->loyaltyobject->insert($batchObject)); } // Make the batch request $batchResponse = $batch->execute(); print "Batch insert response\n"; foreach ($batchResponse as $key => $value) { if ($value instanceof Google_Service_Exception) { print_r($value->getErrors()); continue; } print "{$value->getId()}\n"; } }
Python
หากต้องการเริ่มการผสานรวมใน Python โปรดดู ตัวอย่างโค้ดทั้งหมดบน GitHub
def batch_create_objects(self, issuer_id: str, class_suffix: str): """Batch create Google Wallet objects from an existing class. The request body will be a multiline string. See below for information. https://cloud.google.com/compute/docs/api/how-tos/batch#example Args: issuer_id (str): The issuer ID being used for this request. class_suffix (str): Developer-defined unique ID for this pass class. """ batch = self.client.new_batch_http_request() # Example: Generate three new pass objects for _ in range(3): # Generate a random object suffix object_suffix = str(uuid.uuid4()).replace('[^\\w.-]', '_') # See link below for more information on required properties # https://developers.google.com/wallet/retail/loyalty-cards/rest/v1/loyaltyobject batch_object = { 'id': f'{issuer_id}.{object_suffix}', 'classId': f'{issuer_id}.{class_suffix}', 'state': 'ACTIVE', 'heroImage': { 'sourceUri': { 'uri': 'https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg' }, 'contentDescription': { 'defaultValue': { 'language': 'en-US', 'value': 'Hero image description' } } }, 'textModulesData': [{ 'header': 'Text module header', 'body': 'Text module body', 'id': 'TEXT_MODULE_ID' }], 'linksModuleData': { 'uris': [{ 'uri': 'http://maps.google.com/', 'description': 'Link module URI description', 'id': 'LINK_MODULE_URI_ID' }, { 'uri': 'tel:6505555555', 'description': 'Link module tel description', 'id': 'LINK_MODULE_TEL_ID' }] }, 'imageModulesData': [{ 'mainImage': { 'sourceUri': { 'uri': 'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg' }, 'contentDescription': { 'defaultValue': { 'language': 'en-US', 'value': 'Image module description' } } }, 'id': 'IMAGE_MODULE_ID' }], 'barcode': { 'type': 'QR_CODE', 'value': 'QR code' }, 'locations': [{ 'latitude': 37.424015499999996, 'longitude': -122.09259560000001 }], 'accountId': 'Account id', 'accountName': 'Account name', 'loyaltyPoints': { 'label': 'Points', 'balance': { 'int': 800 } } } batch.add(self.client.loyaltyobject().insert(body=batch_object)) # Invoke the batch API calls response = batch.execute() print('Batch complete')
C#
หากต้องการเริ่มการผสานรวมใน C# โปรดดู ตัวอย่างโค้ดทั้งหมดบน GitHub
/// <summary> /// Batch create Google Wallet objects from an existing class. /// </summary> /// <param name="issuerId">The issuer ID being used for this request.</param> /// <param name="classSuffix">Developer-defined unique ID for this pass class.</param> public async void BatchCreateObjects(string issuerId, string classSuffix) { // The request body will be a multiline string // See below for more information // https://cloud.google.com/compute/docs/api/how-tos/batch//example string data = ""; HttpClient httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( "Bearer", credentials.GetAccessTokenForRequestAsync().Result ); // Example: Generate three new pass objects for (int i = 0; i < 3; i++) { // Generate a random object suffix string objectSuffix = Regex.Replace(Guid.NewGuid().ToString(), "[^\\w.-]", "_"); // See link below for more information on required properties // https://developers.google.com/wallet/retail/loyalty-cards/rest/v1/loyaltyobject LoyaltyObject batchObject = new LoyaltyObject { Id = $"{issuerId}.{objectSuffix}", ClassId = $"{issuerId}.{classSuffix}", State = "ACTIVE", HeroImage = new Image { SourceUri = new ImageUri { Uri = "https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg" }, ContentDescription = new LocalizedString { DefaultValue = new TranslatedString { Language = "en-US", Value = "Hero image description" } } }, TextModulesData = new List<TextModuleData> { new TextModuleData { Header = "Text module header", Body = "Text module body", Id = "TEXT_MODULE_ID" } }, LinksModuleData = new LinksModuleData { Uris = new List<Google.Apis.Walletobjects.v1.Data.Uri> { new Google.Apis.Walletobjects.v1.Data.Uri { UriValue = "http://maps.google.com/", Description = "Link module URI description", Id = "LINK_MODULE_URI_ID" }, new Google.Apis.Walletobjects.v1.Data.Uri { UriValue = "tel:6505555555", Description = "Link module tel description", Id = "LINK_MODULE_TEL_ID" } } }, ImageModulesData = new List<ImageModuleData> { new ImageModuleData { MainImage = new Image { SourceUri = new ImageUri { Uri = "http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg" }, ContentDescription = new LocalizedString { DefaultValue = new TranslatedString { Language = "en-US", Value = "Image module description" } } }, Id = "IMAGE_MODULE_ID" } }, Barcode = new Barcode { Type = "QR_CODE", Value = "QR code" }, Locations = new List<LatLongPoint> { new LatLongPoint { Latitude = 37.424015499999996, Longitude = -122.09259560000001 } }, AccountId = "Account id", AccountName = "Account name", LoyaltyPoints = new LoyaltyPoints { Label = "Points", Balance = new LoyaltyPointsBalance { Int__ = 800 } } }; data += "--batch_createobjectbatch\n"; data += "Content-Type: application/json\n\n"; data += "POST /walletobjects/v1/loyaltyObject/\n\n"; data += JsonConvert.SerializeObject(batchObject) + "\n\n"; } data += "--batch_createobjectbatch--"; // Invoke the batch API calls HttpRequestMessage batchObjectRequest = new HttpRequestMessage( HttpMethod.Post, "https://walletobjects.googleapis.com/batch"); batchObjectRequest.Content = new StringContent(data); batchObjectRequest.Content.Headers.ContentType = new MediaTypeHeaderValue( "multipart/mixed"); // `boundary` is the delimiter between API calls in the batch request batchObjectRequest.Content.Headers.ContentType.Parameters.Add( new NameValueHeaderValue("boundary", "batch_createobjectbatch")); HttpResponseMessage batchObjectResponse = httpClient.Send( batchObjectRequest); string batchObjectContent = await batchObjectResponse .Content .ReadAsStringAsync(); Console.WriteLine("Batch insert response"); Console.WriteLine(batchObjectContent); }
Node.js
หากต้องการเริ่มการผสานรวมในโหนด โปรดดู ตัวอย่างโค้ดทั้งหมดบน GitHub
/** * Batch create Google Wallet objects from an existing class. * * @param {string} issuerId The issuer ID being used for this request. * @param {string} classSuffix Developer-defined unique ID for this pass class. */ async batchCreateObjects(issuerId, classSuffix) { // See below for more information // https://cloud.google.com/compute/docs/api/how-tos/batch#example let data = ''; let batchObject; let objectSuffix; // Example: Generate three new pass objects for (let i = 0; i < 3; i++) { // Generate a random object suffix objectSuffix = uuidv4().replace('[^\w.-]', '_'); // See link below for more information on required properties // https://developers.google.com/wallet/retail/loyalty-cards/rest/v1/loyaltyobject batchObject = { 'id': `${issuerId}.${objectSuffix}`, 'classId': `${issuerId}.${classSuffix}`, 'state': 'ACTIVE', 'heroImage': { 'sourceUri': { 'uri': 'https://farm4.staticflickr.com/3723/11177041115_6e6a3b6f49_o.jpg' }, 'contentDescription': { 'defaultValue': { 'language': 'en-US', 'value': 'Hero image description' } } }, 'textModulesData': [ { 'header': 'Text module header', 'body': 'Text module body', 'id': 'TEXT_MODULE_ID' } ], 'linksModuleData': { 'uris': [ { 'uri': 'http://maps.google.com/', 'description': 'Link module URI description', 'id': 'LINK_MODULE_URI_ID' }, { 'uri': 'tel:6505555555', 'description': 'Link module tel description', 'id': 'LINK_MODULE_TEL_ID' } ] }, 'imageModulesData': [ { 'mainImage': { 'sourceUri': { 'uri': 'http://farm4.staticflickr.com/3738/12440799783_3dc3c20606_b.jpg' }, 'contentDescription': { 'defaultValue': { 'language': 'en-US', 'value': 'Image module description' } } }, 'id': 'IMAGE_MODULE_ID' } ], 'barcode': { 'type': 'QR_CODE', 'value': 'QR code' }, 'locations': [ { 'latitude': 37.424015499999996, 'longitude': -122.09259560000001 } ], 'accountId': 'Account id', 'accountName': 'Account name', 'loyaltyPoints': { 'label': 'Points', 'balance': { 'int': 800 } } }; data += '--batch_createobjectbatch\n'; data += 'Content-Type: application/json\n\n'; data += 'POST /walletobjects/v1/loyaltyObject\n\n'; data += JSON.stringify(batchObject) + '\n\n'; } data += '--batch_createobjectbatch--'; // Invoke the batch API calls let response = await this.client.context._options.auth.request({ url: 'https://walletobjects.googleapis.com/batch', method: 'POST', data: data, headers: { // `boundary` is the delimiter between API calls in the batch request 'Content-Type': 'multipart/mixed; boundary=batch_createobjectbatch' } }); console.log('Batch insert response'); console.log(response); }
Go
หากต้องการเริ่มการผสานรวมใน Go ให้ดูตัวอย่างโค้ดทั้งหมดได้ใน ตัวอย่างโค้ดใน GitHub ของ GitHub
// Batch create Google Wallet objects from an existing class. func (d *demoLoyalty) batchCreateObjects(issuerId, classSuffix string) { data := "" for i := 0; i < 3; i++ { objectSuffix := strings.ReplaceAll(uuid.New().String(), "-", "_") loyaltyObject := new(walletobjects.LoyaltyObject) loyaltyObject.Id = fmt.Sprintf("%s.%s", issuerId, objectSuffix) loyaltyObject.ClassId = fmt.Sprintf("%s.%s", issuerId, classSuffix) loyaltyObject.AccountName = "Account name" loyaltyObject.AccountId = "Account id" loyaltyObject.State = "ACTIVE" loyaltyJson, _ := json.Marshal(loyaltyObject) batchObject := fmt.Sprintf("%s", loyaltyJson) data += "--batch_createobjectbatch\n" data += "Content-Type: application/json\n\n" data += "POST /walletobjects/v1/loyaltyObject\n\n" data += batchObject + "\n\n" } data += "--batch_createobjectbatch--" res, err := d.credentials.Client(oauth2.NoContext).Post("https://walletobjects.googleapis.com/batch", "multipart/mixed; boundary=batch_createobjectbatch", bytes.NewBuffer([]byte(data))) if err != nil { fmt.Println(err) } else { b, _ := io.ReadAll(res.Body) fmt.Printf("Batch insert response:\n%s\n", b) } }