JSON Schema === ###### tags: `File Format` ###### tags: `File Format`, `JSON`, `Schema` <br> [TOC] <br> ## Additional Properties > https://json-schema.org/understanding-json-schema/reference/object#additionalproperties <br> ## 討論 ### JSON Schema 中的 `additionalProperties` 是什麼? - ### gpt-4o (2025/06/03) 在 JSON Schema 中,`additionalProperties` 是用來控制物件中未被 `properties` 或 `patternProperties` 關鍵字明確定義的額外屬性。 ### `additionalProperties` 的用途 當你使用 `properties` 定義了物件的特定屬性時,預設情況下,JSON Schema 仍然允許物件包含其他未定義的屬性。為了控制這些額外屬性的行為,可以使用 `additionalProperties` 關鍵字。 ### `additionalProperties` 的可能取值 1. **布林值 `true`(預設值)**: 允許物件包含任何未在 `properties` 或 `patternProperties` 中定義的屬性。 2. **布林值 `false`**: 禁止物件包含任何未在 `properties` 或 `patternProperties` 中定義的屬性。 **範例**: ```yaml= { "type": "object", "properties": { "number": { "type": "number" }, "street_name": { "type": "string" }, "street_type": { "type": "string", "enum": ["Street", "Avenue", "Boulevard"] } }, "additionalProperties": false } ``` 在上述範例中,物件僅允許包含 `number`、`street_name` 和 `street_type` 這三個屬性,其他任何屬性都將使驗證失敗。 3. **一個 Schema 物件**: 允許物件包含未在 `properties` 或 `patternProperties` 中定義的屬性,但這些屬性必須符合指定的 Schema。 **範例**: ``` { "type": "object", "properties": { "number": { "type": "number" }, "street_name": { "type": "string" }, "street_type": { "type": "string", "enum": ["Street", "Avenue", "Boulevard"] } }, "additionalProperties": { "type": "string" } } ``` 在這個範例中,除了定義的三個屬性外,物件可以包含其他屬性,但這些額外屬性的值必須是字串類型。 ### 與 `patternProperties` 的結合使用 `additionalProperties` 通常與 `patternProperties` 一起使用,以提供更細緻的控制。例如,可以使用正則表達式定義一組屬性名稱的模式,並為這些模式指定 Schema,同時使用 `additionalProperties` 控制其他未匹配的屬性。 **範例**: ``` { "type": "object", "patternProperties": { "^S_": { "type": "string" }, "^I_": { "type": "integer" } }, "additionalProperties": false } ``` 在這個範例中,物件允許屬性名稱以 `S_` 開頭且值為字串,或以 `I_` 開頭且值為整數的屬性,其他任何不符合這些模式的屬性都將被禁止。 ### 小結 `additionalProperties` 是 JSON Schema 中用來控制物件中未明確定義屬性的強大工具。透過適當地設定這個關鍵字,可以精確地定義資料的結構,確保資料的完整性與一致性。 <br> ### 更具體的 `additionalProperties` 情境例子? - ### gpt-4o (2025/06/03) ### 📦 情境 1:限制 API 接收欄位(`additionalProperties: false`) #### ✅ 背景 你有一個表單 API,只希望用戶提交這三個欄位: - `username`(字串) - `email`(字串) - `age`(整數) 你不希望有人亂傳像 `password`、`admin` 這種多餘欄位。 #### 🔧 JSON Schema ```json= { "type": "object", "properties": { "username": { "type": "string" }, "email": { "type": "string", "format": "email" }, "age": { "type": "integer" } }, "required": ["username", "email"], "additionalProperties": false } ``` #### ❌ 錯誤資料(多了 `admin`) ```json= { "username": "alice", "email": "alice@example.com", "age": 25, "admin": true } ``` 這會被拒絕,因為 `admin` 是不被允許的額外欄位。 --- ### 🧩 情境 2:允許擴充欄位但限定格式(`additionalProperties` 是 schema) #### ✅ 背景 你做一個問卷平台,`questions` 是自由增加的,但所有欄位都要是字串。 #### 🔧 JSON Schema ```json= { "type": "object", "properties": { "userId": { "type": "string" } }, "required": ["userId"], "additionalProperties": { "type": "string" } } ``` #### ✅ 合法資料 ```json= { "userId": "abc123", "q1": "Yes", "q2": "No", "q3": "Maybe" } ``` 這是合法的,因為 `q1`、`q2`、`q3` 都是字串。 #### ❌ 錯誤資料(`q2` 不是字串) ```json= { "userId": "abc123", "q1": "Yes", "q2": 42 } ``` 這會被拒絕,因為 `q2` 是整數,不符合 `additionalProperties` 指定的字串類型。 --- ### 🔒 情境 3:使用者設定檔,允許特定開頭欄位(配合 `patternProperties`) #### ✅ 背景 你允許使用者傳送自定義設定,但名稱必須以 `x-` 開頭。 #### 🔧 JSON Schema ```json= { "type": "object", "properties": { "user": { "type": "string" } }, "patternProperties": { "^x-": { "type": "string" } }, "additionalProperties": false } ``` #### ✅ 合法資料 ```json= { "user": "bob", "x-theme": "dark", "x-font": "large" } ``` #### ❌ 錯誤資料(`theme` 不以 `x-` 開頭) ```json= { "user": "bob", "theme": "dark" } ``` 會被拒絕,因為 `theme` 沒有符合 `^x-` 開頭的規則。 <br> {%hackmd vaaMgNRPS4KGJDSFG0ZE0w %}