ในบทความก่อนหน้าของเรา "จะทำอย่างไรเมื่อ API มีโครงสร้างพารามิเตอร์หลายรูปแบบ" เราได้พูดคุยกันว่าเมื่อ API ต้องการโครงสร้างพารามิเตอร์ที่แตกต่างกัน คุณสามารถใช้ oneOf, anyOf หรือ allOf ใน Apidog เพื่อกำหนดโครงสร้างเหล่านั้นได้
เมื่อคุณตั้งค่าโครงสร้างพารามิเตอร์โดยใช้การประกอบสคีมาเหล่านี้ และพารามิเตอร์ของคุณมีฟิลด์ที่ระบุประเภทข้อมูล คุณสามารถทำให้เอกสารมีความชัดเจนยิ่งขึ้นโดยใช้คุณสมบัติ discriminator จากข้อกำหนด OpenAPI เพื่อแยกความแตกต่างระหว่างสคีมาได้อย่างเป็นธรรมชาติมากขึ้น
Discriminator คืออะไร?
ใน OpenAPI บทบาทของ discriminator คือการนำ "polymorphism" จากการเขียนโปรแกรมเชิงวัตถุมาใช้งาน
พูดง่ายๆ คือ มันใช้คุณสมบัติที่ใช้ร่วมกันและค่าเฉพาะของมันเพื่อระบุอย่างชัดเจนว่าควรใช้สคีมาใดในรายการ oneOf หรือ anyOf
ตัวอย่างเช่น ในร้านขายสัตว์เลี้ยง เราจำเป็นต้องใช้สคีมาเพื่ออธิบายสัตว์เลี้ยง (และแมวกับสุนัขมีคุณสมบัติที่แตกต่างกัน)
สคีมาสำหรับสุนัขคือ:
{
"name": "Hotdog",
"age": 3,
"weight": 25.5,
"petType": "dog",
"breed": "Golden Retriever",
"isVaccinated": true,
"walkingSchedule": "Morning and Evening",
"favoriteToys": ["Frisbee", "Tennis Ball"],
"trainingLevel": "Intermediate"
}สคีมาสำหรับแมวคือ:
{
"name": "Meow",
"age": 2,
"weight": 4.2,
"petType": "cat",
"isVaccinated": true,
"isIndoor": true,
"litterBoxType": "Enclosed",
"scratchingPostHeight": 120,
"favoriteSleepingSpot": "Balcony"
}ดังที่คุณเห็น แม้ว่าสคีมาทั้งสองจะมีฟิลด์ทั่วไป เช่น petType, name, age เป็นต้น แต่สุนัขมีฟิลด์เฉพาะ เช่น breed, walkingSchedule เป็นต้น ในขณะที่แมวมีฟิลด์เฉพาะ เช่น isIndoor, litterBoxType เป็นต้น
หากคุณใช้เพียง oneOf เพื่อกำหนดสคีมาเหล่านี้เมื่อออกแบบเอกสาร API เอกสารนั้นสามารถแยกความแตกต่างระหว่างสคีมา dog และ cat ได้ในทางเทคนิค อย่างไรก็ตาม ความสัมพันธ์ของแต่ละประเภทไม่ชัดเจนนัก ผู้อ่านต้องสลับไปมาระหว่างแท็บสคีมาทั้งสองเพื่อเปรียบเทียบ ซึ่งจะสร้างความสับสนเมื่อมีพารามิเตอร์จำนวนมาก

ด้วยการเพิ่ม discriminator เอกสารจะแสดงเมนูแบบเลื่อนลง ซึ่งผู้อ่านสามารถเลือกค่าของ petType (dog หรือ cat ) ได้ เมื่อเลือกแล้ว หน้าจะแสดงสคีมาที่ถูกต้องพร้อมฟิลด์ที่เกี่ยวข้องโดยอัตโนมัติ ซึ่งช่วยลดความจำเป็นในการเปรียบเทียบหลายแท็บและทำให้ความแตกต่างระหว่างแต่ละสคีมาชัดเจนยิ่งขึ้น

discriminator มักใช้ร่วมกับ oneOf หรือ anyOf โดย oneOf กำหนดสคีมาวัตถุที่เป็นไปได้ และ discriminator จะบอกให้ตัวแยกวิเคราะห์ทราบว่าจะใช้สคีมาใดตามประเภทที่เลือก
สิ่งนี้ทำให้วัตถุที่ซับซ้อนมีความชัดเจนยิ่งขึ้น และช่วยให้เครื่องมือสามารถแยกแยะประเภทโดยอัตโนมัติเมื่อแสดงเอกสารหรือสร้างโค้ด
คุณสมบัติการกำหนดค่าของ discriminator
discriminator มีคุณสมบัติหลักสองประการ:
- propertyName: ระบุชื่อฟิลด์ที่ใช้ในการแยกแยะประเภท เช่น
petTypeในตัวอย่างข้างต้น - mapping: กำหนดความสัมพันธ์การแมประหว่างค่าฟิลด์และสคีมาเฉพาะ เช่น
"dog"สอดคล้องกับสคีมาสุนัข และ"cat"สอดคล้องกับสคีมาแมว
ตัวอย่างการกำหนดค่าใน OpenAPI:
discriminator:
propertyName: petType
mapping:
dog: '#/components/schemas/Dog'
cat: '#/components/schemas/Cat'การกำหนดค่า Discriminator ใน Apidog
Apidog รองรับการกำหนดค่า discriminator สองวิธี:
- GUI + JSON Schema
- นำเข้า OpenAPI specs โดยตรง
วิธีที่ 1: GUI + JSON Schema
อันดับแรก สร้างสคีมาใน Apidog เช่น Dog และ Cat:

เปิด Endpoint ที่คุณต้องการใช้สคีมาเหล่านี้ และไปที่ตัวแก้ไขเนื้อหาคำขอ (request body) หรือเนื้อหาการตอบกลับ (response body)
เลือกฟิลด์ที่คุณต้องการกำหนดเป็นส่วนประกอบของสคีมา และเลือก Advanced Settings → Schema Compositions → oneOf

ใน oneOf ให้อ้างอิงสคีมาที่คุณต้องการ เช่น Dog และ Cat

ตอนนี้คุณได้กำหนดสคีมาที่เป็นไปได้หลายรูปแบบผ่าน oneOf แล้ว ถัดไป คุณต้องเพิ่ม discriminator เพื่อระบุวิธีการแยกแยะสคีมาเหล่านี้ คลิก JSON Schema เพื่อเปลี่ยนเป็นโหมดโค้ด:

เพิ่มการกำหนดค่า discriminator ในตำแหน่งที่เหมาะสม (ในระดับเดียวกับ oneOf) ตัวอย่างเช่น:
"discriminator": {
"propertyName": "petType",
"mapping": {
"dog": "#/definitions/190704823",
"cat": "#/definitions/190704706"
}
}ค่าใน mapping เช่น #/definitions/190704823 เป็น ID เฉพาะที่ Apidog สร้างขึ้นภายในสำหรับสคีมา คุณสามารถค้นหาพาธ definitions ที่สอดคล้องกันสำหรับแต่ละสคีมาได้ในแผงการกำหนดค่า JSON Schema

หลังจากกำหนดค่าเสร็จสมบูรณ์ ให้บันทึก ในเอกสาร API คุณสามารถสลับประเภทวัตถุได้อย่างชาญฉลาดตามค่าของฟิลด์ petType

วิธีที่ 2: นำเข้า OpenAPI Specs โดยตรง
นี่เป็นแนวทางมาตรฐานมากขึ้น โดยเฉพาะอย่างยิ่งเหมาะสำหรับทีมที่คุ้นเคยกับเวิร์กโฟลว์แบบ "design-first"
เขียน OpenAPI specs ของคุณโดยมี discriminator รวมอยู่ด้วย จากนั้นนำเข้าสู่ Apidog
ตัวอย่างเช่น ใน OpenAPI specs คำจำกัดความของ discriminator มีดังนี้:
Pet:
oneOf:
- $ref: '#/components/schemas/Dog'
- $ref: '#/components/schemas/Cat'
discriminator:
propertyName: petType
mapping:
dog: '#/components/schemas/Dog'
cat: '#/components/schemas/Cat'คำจำกัดความนี้ระบุไว้อย่างชัดเจนว่า:
- ผ่าน
oneOfระบุว่าวัตถุอาจเป็นประเภทDogหรือCat - ผ่าน
discriminatorระบุการกำหนดประเภทเฉพาะตามค่าของฟิลด์petType - ผ่าน
mappingระบุอย่างชัดเจนว่า"dog"สอดคล้องกับสคีมาDogและ"cat"สอดคล้องกับสคีมาCat
OpenAPI specs ฉบับสมบูรณ์มีดังนี้:
openapi: 3.0.3
info:
title: Pet Shop API
version: 1.0.0
components:
schemas:
Dog:
type: object
properties:
petType:
type: string
enum: [dog]
name:
type: string
age:
type: integer
weight:
type: number
breed:
type: string
isVaccinated:
type: boolean
walkingSchedule:
type: string
favoriteToys:
type: array
items:
type: string
trainingLevel:
type: string
required:
- petType
- name
- age
Cat:
type: object
properties:
petType:
type: string
enum: [cat]
name:
type: string
age:
type: integer
weight:
type: number
isVaccinated:
type: boolean
isIndoor:
type: boolean
litterBoxType:
type: string
scratchingPostHeight:
type: integer
favoriteSleepingSpot:
type: string
required:
- petType
- name
- age
Pet:
oneOf:
- $ref: '#/components/schemas/Dog'
- $ref: '#/components/schemas/Cat'
discriminator:
propertyName: petType
mapping:
dog: '#/components/schemas/Dog'
cat: '#/components/schemas/Cat'
paths:
/pets:
get:
summary: Get pet information
responses:
'200':
description: Successful response
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'หลังจากสร้าง OpenAPI specs เสร็จสมบูรณ์ ให้ใช้คุณสมบัติ import ใน Apidog Apidog จะแยกวิเคราะห์ specs ทั้งหมด สร้างสคีมาและ Endpoint ที่เกี่ยวข้องโดยอัตโนมัติ และจดจำการกำหนดค่า discriminator ได้อย่างถูกต้อง (มีการเพิ่ม enum ที่นี่เพื่อล็อกค่าพารามิเตอร์)

คำถามที่พบบ่อย
1. ควรใช้ Discriminator เมื่อใด?
คุณควรใช้ discriminator ก็ต่อเมื่อ Endpoint ของคุณมีฟิลด์ที่ระบุสคีมาอยู่แล้ว ในตัวอย่างข้างต้น ฟิลด์ petType มีอยู่ในดีไซน์ API และใช้เพื่อแยกความแตกต่างระหว่างประเภทสัตว์เลี้ยง
discriminator เพียงแค่บอกเครื่องมือว่าจะเลือกสคีมาที่ถูกต้องอย่างไรตามค่าของฟิลด์นั้น
หาก Endpoint ของคุณไม่มีฟิลด์ระบุประเภทดังกล่าว discriminator ก็ไม่เหมาะสม—การใช้ oneOf เพียงอย่างเดียวก็เพียงพอแล้ว
นอกจากนี้ หากสคีมาของคุณเรียบง่ายหรือมีการเปลี่ยนแปลงเพียงเล็กน้อย คุณอาจไม่จำเป็นต้องใช้ discriminator เลย
2. ต้องใช้ Discriminator ร่วมกับ oneOf หรือไม่?
ใช่ discriminator ต้องใช้ร่วมกับ oneOf, anyOf หรือ allOf ไม่สามารถกำหนดสคีมาได้ด้วยตัวเอง—แต่จะอธิบายวิธีการแยกแยะระหว่างสคีมาที่เป็นไปได้หลายรูปแบบเท่านั้น
สรุป
discriminator เป็นคุณสมบัติเสริมในข้อกำหนด OpenAPI ที่ใช้เพื่อปรับปรุงประสบการณ์ผู้ใช้ของ oneOf/anyOf/allOf
เมื่อ OpenAPI specs ของคุณมีฟิลด์ที่ใช้ระบุประเภทอยู่แล้ว คุณสามารถกำหนดค่า discriminator ใน Apidog เพื่อทำให้เอกสาร API ชัดเจนและชาญฉลาดมากยิ่งขึ้น
แน่นอนว่า หากคุณพบว่าการกำหนดค่ายุ่งยากหรือสคีมาค่อนข้างเรียบง่าย คุณสามารถใช้เพียงการประกอบสคีมา เช่น oneOf ได้อย่างสมบูรณ์
