XML Schema から JSON Schema 2020-12 への変換規則案

Views: 0

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. 基本原則

  1. JSON Schema の構造は、XML の型と構造を意味的に保持する。

  2. 単純コンテンツ+属性の複合型は、UBL 準拠で “_” キーを用いて要素内容(text content)を表現する。

  3. 属性・要素の区別は、properties で定義するキーが “_” であるものを要素とし、それ以外を属性とする。

  4. 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 に変換するためのガイドラインを提供するものであり、統一的な定義テーブルを用意することで、資料の互換性や再利用性を高めることを目指している。


投稿日

カテゴリー:

, , ,

投稿者:

タグ:

コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です