このブログの更新は Twitterアカウント @m_hiyama で通知されます。
Follow @m_hiyama

メールでのご連絡は hiyama{at}chimaira{dot}org まで。

はじめてのメールはスパムと判定されることがあります。最初は、信頼されているドメインから差し障りのない文面を送っていただけると、スパムと判定されにくいと思います。

参照用 記事

JSONスキーマと列挙型

JSONスキーマを代替する私家版スキーマ言語に関しては:

ウゲーッって感じがしますよね。このウゲーッ感をなんとかしないと使いものになりませんね。



現状のスキーマ言語試案はまだダメダメなところがあるので、もうちょい考えてみます。

と、自己批判的なことを言ったので、引き続き議論します。今、2つの方向から考えていて、1つは現状のスキーマ言語試案に手を入れていく方向、もう1つは別な新しい構文を模索することです。とりあえず、現試案を改善する方策を述べます。

内容:

  1. 列挙型の記述がひどすぎる
  2. 値だけを列挙すればそれで済む
  3. 記述が短くなりました

列挙型の記述がひどすぎる

次は以前に出した例(の一部)です。


Dessert =
string(label = "お飲み物",
enum = ["teaHot", "teaIce",
"coffeeHot", "coffeeIce"],
options = [
(value = "teaHot",
label = "紅茶 (ホット)"),
(value = "teaIce",
label = "紅茶 (アイス)"),
(value = "coffeeHot",
label = "コーヒー (ホット)"),
(value = "coffeeIce",
label = "コーヒー (アイス)")
]
);
オリジナルのJSONスキーマの構文(ただし、スキーマ属性labelを追加)だと:


{
"id" : "Dessert",
"type" : "string",
"label" : "お飲み物",
"enum" : ["teaHot", "teaIce",
"coffeeHot", "coffeeIce"],
"options" : [
{
"value" : "teaHot",
"label" : "紅茶 (ホット)"
},
{
"value" : "teaIce",
"label" : "紅茶 (アイス)"
},
{
"value" : "coffeeHot",
"label" : "コーヒー (ホット)"
},
{
"value" : "coffeeIce",
"label" : "コーヒー (アイス)"
}
]
}

どっちにしろ、重複記述が多くていただけません。options付きの列挙型については、もっとコンパクトな記法が必要です。

値だけを列挙すればそれで済む

列挙型でベースにする型は、整数と文字列を考えれば十分でしょう。単に値のリテラルを並べればそれで列挙型の定義としての情報は十分なので、次のように書けば済みます。


// JSONスキーマの構文
{
"type" : "integer",
"enum" : [1, 2, 3],
}



// 新しい構文
enum [1, 2, 3]

代替構文でも同様な単純化ができます。


// 今での構文
Drink = string(label = "お飲み物",
enum = ["teaHot", "teaIce",
"coffeeHot", "coffeeIce"]
);



// 新しい構文
Drink = enum(label = "お飲み物") [
"teaHot", "teaIce",
"coffeeHot", "coffeeIce"
];

ラベルを書くともっとハッキリと違いが出来ます。


// JSONスキーマの構文
{
"id" : "SMLSelection",
"type" : "integer",
"enum" : [1, 2, 3],
"options" : [
{"value": 1, "label": "Small"},
{"value": 2, "label": "Medium"},
{"value": 3, "label": "Large"}
]
}

// 今での代替構文
Drink = string(label = "お飲み物",
enum = ["teaHot", "teaIce",
"coffeeHot", "coffeeIce"],
options = [
(value = "teaHot",
label = "紅茶 (ホット)"),
(value = "teaIce",
label = "紅茶 (アイス)"),
(value = "coffeeHot",
label = "コーヒー (ホット)"),
(value = "coffeeIce",
label = "コーヒー (アイス)")
]);



// 新しい代替構文
SMLSelection = enum [
1 : "Small",
2 : "Medium",
3 : "Large"
];

// 新しい代替構文
Drink = enum(label = "お飲み物") [
"teaHot" : "紅茶 (ホット)",
"teaIce" : "紅茶 (アイス)",
"coffeeHot" : "コーヒー (ホット)",
"coffeeIce" : "コーヒー (アイス)"
];

記述が短くなりました

ランチの注文全体を新しい構文で書き直してみると:


LunchOrder =
object(label = "ランチご注文") {
"ident" : object(label = "ランチ会員情報") {
"name" : string(label = "お名前"),
"memberNum" : integer(label = "会員番号")
},
"order" : object(label = "本日のご注文") {
"mainDish" : enum(label = "メイン") [
"special" : "日替わり",
"fish", : "魚",
"meat", : "肉"
],
"drink" : enum(label = "お飲み物") [
"teaHot" : "紅茶 (ホット)",
"teaIce" : "紅茶 (アイス)",
"coffeeHot" : "コーヒー (ホット)",
"coffeeIce" : "コーヒー (アイス)"
]
"dessert" : set(label = "デザート") [
enum [
"pudding" : "プリン",
"strawberryShortcake" : "苺ショートケーキ",
"bavarianCream" : "ババロア",
"gateauChocolat" : "ガトーショコラ"
]
]
} // 本日のご注文
} // ランチご注文
;

だいぶ短く書けるようになりました。もっと短くできそうなところは:

  1. label = "ラベル文字列" が頻繁に出てくるので、文字列が出現したらラベルと解釈する。object(label = "ランチご注文")object("ランチご注文") と書ける。
  2. setとenumの組み合わせが多いなら、setOfEnumのようなキーワードを導入する。

こんな細かいことをやるやらないは別にして、列挙型にはまだ問題が残っています。次の機会に議論します。それと、別な新しい構文についてもいずれ話します。