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 %}