Amazon EC2(Linux)に UN/CEFACT spec-JSONschemaテスト環境構築

Views: 3

1. Amazon EC2(Linux)に UN/CEFACT spec-JSONschema リポジトリ をクローン

Amazon EC2(Linux)に UN/CEFACT spec-JSONschema リポジトリ をクローンするには、以下の手順で行えます。

✅ 手順:GitHub リポジトリをクローンする(Amazon Linux 2/2023 共通)

1.1. 必要なパッケージのインストール

sudo dnf install -y git  # Amazon Linux 2023 の場合
# sudo yum install -y git  # Amazon Linux 2 の場合

1.2. 任意の作業ディレクトリに移動(例:ホームディレクトリ)

cd ~
mkdir uncefact && cd uncefact

1.3. リポジトリをクローン

git clone https://github.com/uncefact/spec-JSONschema.git

出力例:

Cloning into 'spec-JSONschema'...
remote: Enumerating objects: ...
remote: Counting objects: ...
...

1.4. 確認

✅ 内容確認

リポジトリには次のような構造のファイルが含まれています:

hema/
├── JSONschema2020-12/
│   ├── library/
│   │   └── BuyShipPay/
│   │       └── D23B/
│   │           └── BasicComponents.json
├── LICENSE
├── README.md
...

✅ 補足(更新・同期)

最新版を取得するにはクローン後に以下を実行:

git pull origin main

2. XBRL GL JSON Schema 対応テスト環境セットアップ手順

📌 目的

2.1. 前提環境の準備(Amazon Linux 2023)

ajv などで JSON の妥当性を検証する開発環境を Amazon Linux 2023(または他のLinux)上にセットアップ
# Node.js と Git のインストール
sudo dnf install -y nodejs git
# 必要であれば tree も
sudo dnf install -y tree

2.2. 作業ディレクトリ作成とAJV環境構築

コマンド

mkdir ~/xbrl-gl-jsonschema && cd ~/xbrl-gl-jsonschema
npm init -y
npm install ajv ajv-formats

実行結果

$ mkdir ~/xbrl-gl-jsonschema && cd ~/xbrl-gl-jsonschema
npm init -y
npm install ajv ajv-formats
Wrote to /home/ec2-user/xbrl-gl-jsonschema/package.json:

{
  "name": "xbrl-gl-jsonschema",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": ""
}

added 6 packages, and audited 7 packages in 2s

2 packages are looking for funding
  run npm fund for details

found 0 vulnerabilities

ChatGPT

👍 完了です!
xbrl-gl-jsonschema 環境が正常にセットアップされ、ajv(JSON Schema バリデータ)と ajv-formats(フォーマット拡張)がインストールされました。

3. XBRL GL JSON

xbrl-gl-instance.json

インスタンス文書

{
    "$schema": "./xbrl-gl-cor-schema.json",
    "accountingEntries": [
        {
            "entryHeader": [
                {
                    "id": {
                        "content": "Book1"
                    },
                    "date": {
                        "content": "2025-05-12"
                    },
                    "description": {
                        "content": "test book"
                    },
                    "entryDetail": [
                        {
                            "lineNumber": {
                                "content": "1"
                            },
                            "description": {
                                "content": "Test entry"
                            },
                            "debitAmount": {
                                "content": "1000",
                                "currencyId": "JPY"
                            },
                            "creditAmount": {
                                "content": "1000",
                                "currencyId": "JPY"
                            },
                            "accountCode": {
                                "content": "JSD0010"
                            }
                        }
                    ]
                }
            ]
        }
    ]
}
xbrl-gl-cor.json

スキーマ定義

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "$id": "http://xbrl.org/XBRL-GL-YYYY-MM-DD/schemas/gl-cor.json",
    "title": "XBRL GL Core Module Schema (Garden of Eden)",
    "description": "Fully modular schema where all definitions and properties are declared globally and referenced.",
    "type": "object",
    "properties": {
        "accountingEntries": {
            "$ref": "#/$defs/AccountingEntries"
        }
    },
    "required": [
        "accountingEntries"
    ],
    "$defs": {
        "AccountingEntries": {
            "type": "array",
            "items": {
                "$ref": "#/$defs/AccountingEntry"
            }
        },
        "AccountingEntry": {
            "type": "object",
            "properties": {
                "entryHeader": {
                    "$ref": "#/$defs/EntryHeaders"
                }
            },
            "required": [
                "entryHeader"
            ]
        },
        "EntryHeaders": {
            "type": "array",
            "items": {
                "$ref": "#/$defs/EntryHeader"
            }
        },
        "EntryHeader": {
            "type": "object",
            "properties": {
                "id": {
                    "$ref": "#/$defs/ID"
                },
                "date": {
                    "$ref": "#/$defs/Date"
                },
                "description": {
                    "$ref": "#/$defs/Description"
                },
                "entryDetail": {
                    "$ref": "#/$defs/EntryDetails"
                }
            },
            "required": [
                "id",
                "date"
            ]
        },
        "EntryDetails": {
            "type": "array",
            "items": {
                "$ref": "#/$defs/EntryDetail"
            }
        },
        "EntryDetail": {
            "type": "object",
            "properties": {
                "lineNumber": {
                    "$ref": "#/$defs/LineNumber"
                },
                "accountCode": {
                    "$ref": "#/$defs/AccountCode"
                },
                "debitAmount": {
                    "$ref": "#/$defs/DebitAmount"
                },
                "creditAmount": {
                    "$ref": "#/$defs/CreditAmount"
                },
                "description": {
                    "$ref": "#/$defs/Description"
                }
            },
            "required": [
                "lineNumber",
                "accountCode"
            ]
        },
        "ID": {
            "$ref": "D23B/UNECE-BasicComponents.json#/$defs/udt/$defs/idType"
        },
        "Date": {
            "$ref": "D23B/UNECE-BasicComponents.json#/$defs/udt/$defs/dateType"
        },
        "Description": {
            "$ref": "D23B/UNECE-BasicComponents.json#/$defs/udt/$defs/textType"
        },
        "LineNumber": {
            "$ref": "D23B/UNECE-BasicComponents.json#/$defs/udt/$defs/numericType"
        },
        "AccountCode": {
            "$ref": "D23B/UNECE-BasicComponents.json#/$defs/udt/$defs/codeType"
        },
        "DebitAmount": {
            "$ref": "D23B/UNECE-BasicComponents.json#/$defs/udt/$defs/amountType"
        },
        "CreditAmount": {
            "$ref": "D23B/UNECE-BasicComponents.json#/$defs/udt/$defs/amountType"
        }
    }
}

スキーマ定義では、UN/CEFACTが提供するUDT(Unqualified Data Type)定義を参照しています。

ChatGPT

✅ 今の構成概要

xbrl-gl-instance.json はインスタンス(データ)
xbrl-gl-cor-schema.json(誤:xbrl-gl-cor.json)は JSON Schema 本体
$defs を中心にモジュール定義している
各基本型(idType, amountType など)は UNECE-BasicComponents.json から $ref している(D23B/)

3.1. ディレクトリ構造を準備

mkdir -p schemas/D23B
mv xbrl-gl-cor.json schemas/xbrl-gl-cor-schema.json
mv xbrl-gl-instance.json instance.json

次に UNECE BasicComponents.json を取得:

curl -o schemas/D23B/UNECE-BasicComponents.json \
  https://raw.githubusercontent.com/uncefact/spec-JSONschema/main/JSONschema2020-12/library/BuyShipPay/D23B/UNECE-BasicComponents.json

3.2. 検証スクリプト validate.js を作成

const Ajv2020 = require("ajv/dist/2020").default;
const addFormats = require("ajv-formats");
const fs = require("fs");
const path = require("path");

// AJVインスタンス作成
const ajv = new Ajv2020({
  strict: false,
  loadSchema: async (uri) => {
    const filePath = path.resolve("schemas", uri.replace(/^.*\/D23B\//, "D23B/"));
    return JSON.parse(fs.readFileSync(filePath));
  }
});
addFormats(ajv);

// スキーマとデータの読み込み
(async () => {
  const schema = JSON.parse(fs.readFileSync("schemas/xbrl-gl-cor-schema.json"));
  const data = JSON.parse(fs.readFileSync("instance.json"));

  // 外部参照を含むスキーマを非同期にcompile
  const validate = await ajv.compileAsync(schema);
  const valid = validate(data);

  if (valid) {
    console.log("✅ Valid!");
  } else {
    console.error("❌ Validation errors:", validate.errors);
  }
})();

3.3. 実行

node validate.js

✅ 注意点

$ref のパス “D23B/UNECE-BasicComponents.json#…​” は ローカル相対パスになるため、validate.js で loadSchema() を使って手動解決が必要。
Ajv.compileAsync() は $ref 解決のために必須。
JSON Schema の $schema は “https://json-schema.org/draft/2020-12/schema” にするとさらに将来的に整合性が良いです(今は draft-07 になっている)。

3.4. 現状のディレクトリ構成

$ tree -L 3
.
├── jsonschema-dev
│   ├── node_modules
│   │   ├── ajv
│   │   ├── ajv-formats
│   │   ├── fast-deep-equal
│   │   ├── fast-uri
│   │   ├── json-schema-traverse
│   │   └── require-from-string
│   ├── package-lock.json
│   ├── package.json
│   └── validate.js
├── uncefact
│   └── spec-JSONschema
│       ├── CODEOWNERS
│       ├── JSONschema2020-12
│       ├── README.md
│       ├── compatibility
│       ├── examples
│       └── images
└── xbrl-gl-jsonschema
    ├── node_modules
    │   ├── ajv
    │   ├── ajv-formats
    │   ├── fast-deep-equal
    │   ├── fast-uri
    │   ├── json-schema-traverse
    │   └── require-from-string
    ├── package-lock.json
    └── package.json

22 directories, 7 files

ChatGPT
ありがとうございます。現在のディレクトリ構成を見る限り、uncefact/spec-JSONschema/JSONschema2020-12/library/BuyShipPay/D23B/UNECE-BasicComponents.json を XBRL GL用 JSON Schema の $ref で参照する準備は整っています。

✅ 次のステップ:xbrl-gl-cor-schema.json と xbrl-gl-instance.json を追加
まず、XBRL GL 用スキーマとインスタンスファイルを配置します:

mkdir -p ~/xbrl-gl-jsonschema/schemas
mkdir -p ~/xbrl-gl-jsonschema/samples

🔹 xbrl-gl-cor-schema.json を作成(schemas 配下)

nano ~/xbrl-gl-jsonschema/schemas/xbrl-gl-cor-schema.json

その中で UNECE-BasicComponents.json を以下のように相対参照:

"DebitAmount": {
  "$ref": "../../uncefact/spec-JSONschema/JSONschema2020-12/library/BuyShipPay/D23B/UNECE-BasicComponents.json#/$defs/udt/$defs/amountType"
}

必要なすべての $ref をこのパターンにします。

🔹 xbrl-gl-instance.json を作成(samples 配下)

✅ 検証スクリプトの配置と実行
🔹 validate.js の作成(ルートディレクトリ)

const Ajv = require("ajv/dist/2020").default;
const addFormats = require("ajv-formats");
const fs = require("fs").promises;
const path = require("path");

const ajv = new Ajv({
  strict: false,
  loadSchema: async (uri) => {
    const base = path.resolve(__dirname, "uncefact/spec-JSONschema/JSONschema2020-12/library/BuyShipPay/D23B");
    if (uri.includes("UNECE-BasicComponents.json")) {
      const fullPath = path.join(base, "UNECE-BasicComponents.json");
      return JSON.parse(await fs.readFile(fullPath, "utf8"));
    }
    throw new Error(`Unknown schema URI: ${uri}`);
  }
});

addFormats(ajv);

(async () => {
  const schema = JSON.parse(await fs.readFile("schemas/xbrl-gl-cor-schema.json", "utf8"));
  const data = JSON.parse(await fs.readFile("samples/xbrl-gl-instance.json", "utf8"));

  const validate = await ajv.compileAsync(schema);
  const valid = validate(data);

  if (valid) {
    console.log("✅ Valid!");
  } else {
    console.error("❌ Validation errors:");
    console.error(validate.errors);
  }
})();

✅ 実行

cd ~/xbrl-gl-jsonschema
node validate.js

✅ 結果例
成功 → ✅ Valid!

エラー → エラー内容が validate.errors に出力されます(パスや $ref の指定ミスも含め)

onst fs = require("fs").promises;
const path = require("path");
const Ajv2020 = require("ajv/dist/2020");
const addFormats = require("ajv-formats");

async function loadSchema(uri) {
  const base = path.resolve(__dirname, "schemas");

  // Draft 2020-12 メインスキーマ
  if (uri === "http://json-schema.org/draft/2020-12/schema") {
    const fullPath = path.join(base, "draft2020-12.json");
    const schema = JSON.parse(await fs.readFile(fullPath, "utf8"));
    delete schema["$id"];
    return schema;
  }

  // 各 vocabulary メタスキーマ
  const vocabularies = [
    "core",
    "applicator",
    "unevaluated",
    "validation",
    "meta-data",
    "format-annotation",
    "content"
  ];

  for (const name of vocabularies) {
    if (uri === `http://json-schema.org/draft/2020-12/meta/${name}`) {
      const fullPath = path.join(base, "meta", `${name}.json`);
      const schema = JSON.parse(await fs.readFile(fullPath, "utf8"));
      delete schema["$id"];
      return schema;
    }
  }

  // その他カスタムスキーマ
  if (uri.includes("UNECE-BasicComponents.json")) {
    const fullPath = path.join(
      __dirname,
      "../uncefact/spec-JSONschema/JSONschema2020-12/library/BuyShipPay/D23B/UNECE-BasicComponents.json"
    );
    return JSON.parse(await fs.readFile(fullPath, "utf8"));
  }

  if (uri.includes("codelists/")) {
    const fileName = path.basename(uri);
    const fullPath = path.join(
      __dirname,
      "../uncefact/spec-JSONschema/JSONschema2020-12/library/BuyShipPay/D23B/codelists",
      fileName
    );
    return JSON.parse(await fs.readFile(fullPath, "utf8"));
  }

  throw new Error(`Unknown schema URI: ${uri}`);
}

const ajv = new Ajv2020({
  loadSchema,
  strict: false
});
addFormats(ajv);

(async () => {
  try {
    const schemaPath = path.join(__dirname, "schemas/xbrl-gl-cor-schema.json");
    const instancePath = path.join(__dirname, "samples/xbrl-gl-instance.json");

    const schema = JSON.parse(await fs.readFile(schemaPath, "utf8"));
    const data = JSON.parse(await fs.readFile(instancePath, "utf8"));

    const validate = await ajv.compileAsync(schema);
    const valid = validate(data);

    if (valid) {
      console.log(" Validation successful: data is valid against the schema.");
    } else {
      console.error(" Validation errors:");
      console.error(validate.errors);
    }
  } catch (err) {
    console.error(" Runtime error:", err);
  }
})();


投稿日

カテゴリー:

, , , ,

投稿者:

タグ:

コメント

コメントを残す

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