Views: 0
XML Schema から JSON Schema 2020-12 への変換規則案
2025-06-10
1. 目的
本規格は、XML Schema(XSD)で定義された業務文書やデータモデルを、JSON Schema(バージョン 2020-12)形式に変換するための一貫したルールを定め、両形式間の意味論的互換性を確保することを目的とする。
2. 適用範囲
本規則は以下の XML Schema 構造に対する変換を対象とする:
-
xs:element
-
xs:complexType
-
xs:simpleType
-
xs:sequence
-
xs:all
-
xs:choice
-
xs:attribute
-
xs:enumeration
-
xs:pattern
-
xs:minOccurs / xs:maxOccurs
3. 基本原則
-
JSON Schema の構造は、XML の型と構造を意味的に保持する。
-
単純コンテンツ+属性の複合型は、UBL 準拠で “_” キーを用いて要素内容(text content)を表現する。
-
属性・要素の区別は、
properties
で定義するキーが “_” であるものを要素とし、それ以外を属性とする。 -
xs:sequence
によって定義された順序は “x-order” により保持される。
4. 要素および型の変換規則
XML Schema 要素 | JSON Schema 対応構造 | 備考 |
---|---|---|
xs:element |
properties または items |
要素名に対応 |
xs:complexType |
type: object + properties |
複合構造 |
xs:simpleType |
type: string など + 制約 |
列挙や正規表現可 |
xs:sequence |
properties + x-order |
順序保持のための注記 |
xs:all |
properties のみ |
順不同 |
xs:choice(排他) |
oneOf + required |
相互排他 |
xs:choice(任意) |
anyOf + required |
任意選択 |
xs:attribute |
属性名をキーとする |
“_” 以外のすべて |
xs:enumeration |
enum |
値の制約 |
xs:pattern |
pattern |
文字列制約 |
minOccurs, maxOccurs |
required, minItems, maxItems |
出現数制御 |
5. sequence, all, choice の変換
5.1. xs:sequence
XML において定義された要素順を尊重する必要があるため、x-order
キーを付加して順序情報を保持する。
<xs:sequence>
<xs:element name="FirstName" type="xs:string"/>
<xs:element name="LastName" type="xs:string"/>
</xs:sequence>
➡ JSON Schema:
{
"type": "object",
"properties": {
"FirstName": { "type": "string", "x-order": 1 },
"LastName": { "type": "string", "x-order": 2 }
},
"required": ["FirstName", "LastName"]
}
5.2. xs:all
要素の順序を問わない構造であり、JSON の properties
にそのまま展開される。
<xs:all>
<xs:element name="City" type="xs:string"/>
<xs:element name="PostalCode" type="xs:string"/>
</xs:all>
➡ JSON Schema:
{
"type": "object",
"properties": {
"City": { "type": "string" },
"PostalCode": { "type": "string" }
},
"required": ["City", "PostalCode"]
}
5.3. xs:choice(排他的選択)
<xs:choice>
<xs:element name="CreditCard" type="xs:string"/>
<xs:element name="PayPal" type="xs:string"/>
</xs:choice>
➡ JSON Schema:
{
"type": "object",
"properties": {
"CreditCard": { "type": "string" },
"PayPal": { "type": "string" }
},
"oneOf": [
{ "required": ["CreditCard"] },
{ "required": ["PayPal"] }
]
}
6. 拡張アノテーションと補足情報
-
“x-order” は順序の保持のための補助情報であり、JSON Schema バリデーションには影響しない。
-
“_” は element の値本体であることを示すための予約語として使用するが、JSON Schema 仕様上のキーワードではない。
本変換規則は、XML Schema と JSON Schema の相互運用を実現し、セマンティックな意味の喪失を最小限に抑えつつ、UI・文書出力・自動検証等において整合的なデータ処理を可能とするものである。
7. 単純コンテンツ型の例
<xs:complexType name="AmountType">
<xs:simpleContent>
<xs:extension base="xs:decimal">
<xs:attribute name="currencyID" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
➡ JSON Schema:
{
"$defs": {
"AmountType": {
"type": "object",
"properties": {
"_": { "type": "number" },
"currencyID": { "type": "string" }
},
"required": ["_"]
}
}
}
8. 各設計パターンでの XML Schema / JSON Schema の構造比較
XML Schema の設計パターンは、主に「要素を流用するか」「型を流用するか」、あるいは「両方を明示的に分離するか」によって分類できる。
設計パターン | 要素の流用 | 型の流用 | 特徴 |
---|---|---|---|
Russian Doll |
✗ |
✗ |
要素と型をセットで定義し、入れ子構造が深くなるが自己完結型。 |
Salami Slice |
◯ |
✗ |
要素定義を再利用。つなぎやすいが、意味的再利用性は低い。 |
Venetian Blind |
✗ |
◯ |
要素ごとに型を分離し型を再利用。保守性が高い。 |
Garden of Eden |
◯ |
◯ |
要素・型をすべて別定義し最大限の再利用性を持つ。 |
8.1. XML/JSONインスタンス例
以下に示すのは、すべての設計パターンで共通に用いられる、基本的な注文書 (Order) インスタンス構造の例である。
XML インスタンス例
<Order>
<OrderID>ORD-001</OrderID>
<OrderDate>2025-06-01</OrderDate>
<Line>
<LineNumber>1</LineNumber>
<Product>Widget</Product>
<UnitPrice currencyID="JPY">100</UnitPrice>
<Quantity>2</Quantity>
<Amount currencyID="JPY">200</Amount>
</Line>
<Line>
<LineNumber>2</LineNumber>
<Product>Gadget</Product>
<UnitPrice currencyID="JPY">500</UnitPrice>
<Quantity>1</Quantity>
<Amount currencyID="JPY">500</Amount>
</Line>
</Order>
JSON インスタンス例
{
"OrderID": "ORD-001",
"OrderDate": "2025-06-01",
"Line": [
{
"LineNumber": "1",
"Product": "Widget",
"UnitPrice": {
"_": 100,
"currencyID": "JPY"
},
"Quantity": 2,
"Amount": {
"_": 200,
"currencyID": "JPY"
}
},
{
"LineNumber": "2",
"Product": "Gadget",
"UnitPrice": {
"_": 500,
"currencyID": "JPY"
},
"Quantity": 1,
"Amount": {
"_": 500,
"currencyID": "JPY"
}
}
]
}
8.2. Russian Doll(ロシア人形)
-
特徴: 型と要素をすべて内包的に定義し、構造を閉じたまま設計
<xs:element name="Order">
<xs:complexType>
<xs:sequence>
<xs:element name="OrderID" type="xs:string"/>
<xs:element name="OrderDate" type="xs:date"/>
<xs:element name="Line">
<xs:complexType>
<xs:sequence>
<xs:element name="LineNumber" type="xs:string"/>
<xs:element name="Product" type="xs:string"/>
<xs:element name="UnitPrice">
<xs:simpleContent>
<xs:extension base="xs:decimal">
<xs:attribute name="currencyID" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:element>
<xs:element name="Quantity" type="xs:decimal"/>
<xs:element name="Amount">
<xs:simpleContent>
<xs:extension base="xs:decimal">
<xs:attribute name="currencyID" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
➡ JSON Schema:(すべて inline 定義)
{
"$defs": {
"Order": {
"type": "object",
"properties": {
"OrderID": { "type": "string" },
"OrderDate": { "type": "string" },
"Line": {
"type": "array",
"items" {
"type": "object",
"properties": {
"LineNumber": { "type": "string" },
"Product": { "type": "string" },
"UnitPrice": {
"type": "object",
"properties": {
"_": { "type": "number" },
"currencyID": { "type": "string" }
},
"required": ["_", "currencyID"]
},
"Quantity": { "type": "number" },
"Amount": {
"type": "object",
"properties": {
"_": { "type": "number" },
"currencyID": { "type": "string" }
},
"required": ["_", "currencyID"]
}
},
"required": ["Product", "Amount"]
}
}
},
"required": ["OrderID", "OrderDate", "Line"]
}
}
}
8.3. Salami Slice(サラミソーセージ)
-
特徴: 要素を独立に定義し、ref 属性で再利用
<xs:element name="Order">
<xs:complexType>
<xs:sequence>
<xs:element ref="OrderID"/>
<xs:element ref="OrderDate"/>
<xs:element ref="Line"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="OrderID" type="xs:string"/>
<xs:element name="OrderDate" type="xs:date"/>
<xs:element name="Line">
<xs:complexType>
<xs:sequence>
<xs:element ref="LineNumber"/>
<xs:element ref="Product"/>
<xs:element ref="UnitPrice"/>
<xs:element ref="Quantity"/>
<xs:element ref="Amount"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="LineNumber" type="xs:string"/>
<xs:element name="Product" type="xs:string"/>
<xs:element name="UnitPrice" type="AmountType"/>
<xs:element name="Quantity" type="xs:decimal"/>
<xs:element name="Amount" type="AmountType"/>
<xs:complexType name="AmountType">
<xs:simpleContent>
<xs:extension base="xs:decimal">
<xs:attribute name="currencyID" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
➡ JSON Schema:
(要素名がそれぞれ $defs で定義され、下位要素を $ref によって参照する。)
{
"$defs": {
"Order": {
"type": "object",
"properties": {
"OrderID": { "$ref": "#/$defs/OrderID" },
"OrderDate": { "$ref": "#/$defs/OrderDate" },
"Line": { "$ref": "#/$defs/Line" }
},
"required": ["OrderID", "OrderDate", "Line"]
},
"OrderID": { "type": "string" },
"OrderDate": { "type": "string" },
"Line": {
"type": "array",
"items" {
"type": "object",
"properties": {
"LineNumber": { "$ref": "#/$defs/LineNumber" },
"Product": { "$ref": "#/$defs/Product" },
"UnitPrice": { "$ref": "#/$defs/UnitPrice" },
"Quantity": { "$ref": "#/$defs/Quantity" },
"Amount": { "$ref": "#/$defs/Amount" }
},
"required": ["LineNumber", "Product", "Amount"]
}
},
"LineNumber": { "type": "string" },
"Product": { "type": "string" },
"UnitPrice": { "$ref": "#/$defs/AmountType" },
"Quantity": { "type": "number" },
"Amount": { "$ref": "#/$defs/AmountType" },
"AmountType": {
"type": "object",
"properties": {
"_": { "type": "number" },
"currencyID": { "type": "string" }
},
"required": ["_", "currencyID"]
}
}
}
8.4. Venetian Blind(ベニスのブラインド)
-
特徴: 型を別定義し、要素はその型を適用する
<xs:element name="Order" type="OrderType"/>
<xs:complexType name="OrderType">
<xs:sequence>
<xs:element name="OrderID" type="xs:string"/>
<xs:element name="OrderDate" type="xs:date"/>
<xs:element name="Line" type="LineType"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="LineType">
<xs:sequence>
<xs:element name="LineNumber" type="xs:string"/>
<xs:element name="Product" type="xs:string"/>
<xs:element name="UnitPrice" type="AmountType"/>
<xs:element name="Quantity" type="xs:decimal"/>
<xs:element name="Amount" type="AmountType"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="AmountType">
<xs:simpleContent>
<xs:extension base="xs:decimal">
<xs:attribute name="currencyID" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
➡ JSON Schema:
(OrderType を別定義して参照)
{
"$defs": {
"Order": { "$ref": "#/$defs/OrderType" },
"OrderType": {
"type": "object",
"properties": {
"OrderID": { "type": "string" },
"OrderDate": { "type": "string" },
"Line": { "$ref": "#/$defs/LineType" }
},
"required": ["OrderID", "OrderDate", "Line"]
},
"LineType": {
"type": "array",
"items" {
"type": "object",
"properties": {
"LineNumber": { "type": "string" },
"Product": { "type": "string" },
"UnitPrice": { "$ref": "#/$defs/AmountType" },
"Quantity": { "type": "number" },
"Amount": { "$ref": "#/$defs/AmountType" }
},
"required": ["LineNumber", "Product", "Amount"]
}
},
"AmountType": {
"type": "object",
"properties": {
"_": { "type": "number" },
"currencyID": { "type": "string" }
},
"required": ["_", "currencyID"]
}
}
}
8.5. Garden of Eden(エデンの園)
-
特徴: 要素および型をすべて別定義する。最大の再利用性と拡張性がある。
<xs:element name="Order" type="OrderType"/>
<xs:complexType name="OrderType">
<xs:sequence>
<xs:element ref="OrderID"/>
<xs:element ref="OrderDate"/>
<xs:element ref="Line"/>
</xs:sequence>
</xs:complexType>
<xs:element name="OrderID" type="xs:string"/>
<xs:element name="OrderDate" type="xs:date"/>
<xs:element name="Line" type="LineType"/>
<xs:complexType name="LineType">
<xs:sequence>
<xs:element ref="LineNumber"/>
<xs:element ref="Product"/>
<xs:element ref="UnitPrice"/>
<xs:element ref="Quantity"/>
<xs:element ref="Amount"/>
</xs:sequence>
</xs:complexType>
<xs:element name="LineNumber" type="xs:string"/>
<xs:element name="Product" type="xs:string"/>
<xs:element name="UnitPrice" type="AmountType"/>
<xs:element name="Quantity" type="xs:decimal"/>
<xs:element name="Amount" type="AmountType"/>
<xs:complexType name="AmountType">
<xs:simpleContent>
<xs:extension base="xs:decimal">
<xs:attribute name="currencyID" type="xs:string"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
➡ JSON Schema:
(すべての要素・型が $defs にて明示的に定義され、相互に参照する。)
{
"$defs": {
"Order": { "$ref": "#/$defs/OrderType" },
"OrderType": {
"type": "object",
"properties": {
"OrderID": { "$ref": "#/$defs/OrderID" },
"OrderDate": { "$ref": "#/$defs/OrderDate" },
"Line": { "$ref": "#/$defs/Line" }
},
"required": ["OrderID", "OrderDate", "Line"]
},
"OrderID": { "type": "string" },
"OrderDate": { "type": "string" },
"Line": { "$ref": "#/$ref/LineType"},
"LineType": {
"type": "array",
"items" {
"type": "object",
"properties": {
"LineNumber": { "$ref": "#/$defs/LineNumber" },
"Product": { "$ref": "#/$defs/Product" },
"UnitPrice": { "$ref": "#/$defs/UnitPrice" },
"Quantity": { "$ref": "#/$defs/Quantity" },
"Amount": { "$ref": "#/$defs/Amount" }
},
"required": ["LineNumber", "Product", "Amount"]
}
},
"LineNumber": { "type": "string" },
"Product": { "type": "string" },
"Quantity": { "type": "number" },
"UnitPrice": { "$ref": "#/$defs/AmountType" },
"Amount": { "$ref": "#/$defs/AmountType" },
"AmountType": {
"type": "object",
"properties": {
"_": { "type": "number" },
"currencyID": { "type": "string" }
},
"required": ["_", "currencyID"]
}
}
}
9. 結論
本設計規則は、不同なパターンで設計された XML Schema を、意味論を保ったまま JSON Schema 2020-12 に変換するためのガイドラインを提供するものであり、統一的な定義テーブルを用意することで、資料の互換性や再利用性を高めることを目指している。
コメントを残す