JSONやYAMLのデータ構造をチェックするライブラリStrongJSONのご紹介

JSONYAMLを使うと、かなり複雑なデータが作成できますが、これが意図通りの形式になっているかを確認するのは自明ではありません。XMLにはXML Schemaがありますが、そんな感じのものがJSONにも欲しかったので、作りました。

github.com

こんな感じで使います。

Schema = StrongJSON.new do
  let :phone, object(phone: string)
  let :email, object(email: string)
  let :contact, enum(phone, email)
  let :person, object(name: string, contacts: array(contact))
end

json = Schema.person.coerce(JSON.parse(input, symbolize_names: true))  # symbolize_namesが必要です

最新バージョンは1.1とかで、最近「人間にも読めるエラーメッセージ」を実現しましたので、みなさまご活用ください。例えばテストにある例なんですが、

TypeError at $.items[0].price: expected=numeric, value=[]
 "price" expected to be numeric
  0 expected to be item
   "items" expected to be items
    $ expected to be checkout

Where:
  item = { "name": string, "count": numeric, "price": numeric }
  items = array(item)
  checkout = {
    "items": items,
    "change": optional(number),
    "type": enum(1, symbol),
    "customer": optional(
      {
        "name": string,
        "id": string,
        "birthday": string,
        "gender": enum("man", "woman", "other"),
        "phone": string
      }
    )
  }

とか出せるので、少し頑張れば人間にも読めるんじゃないかなあ。そのままアプリケーションに組み込んで使っている例としては、 sider/goodcheckがあります。そのままアプリケーションに組み込めば良いということで、YAMLファイルとかで設定を書かせるときに、validationできて便利ではないかと思います。

JSON Schema

さて、ところで世の中にはJSON Schemaというものがあることをご存じの人がいるでしょう。JSON Schemaではダメなのかというと、まあ別に良いんですけど、

  • SchemaもJSONになっていて欲しい気持ちが別にない → Ruby DSLでSchemaを書くようにした
  • 「数字」とか「文字列」とかそういう感じがテストしたいのであって、「電話番号」みたいなデータ型はいらない

という感じです。

YAMLでは

RubyYAMLライブラリだと、まあ大体JSONみたいなデータ構造になれるので、それでいけます。JSON以外のデータ構造もできたと思いますが、そういうのはダメです。

どういう名前なんこれ??

RailsのStrong parametersからの借用です。Strong parametersは、クエリパラメータみたいな構造は上手く処理できるのですが、JSONみたいなのを扱おうとすると幸せな感じではないので作りました。

が、実はこのライブラリは5年くらい前から作っていて、当時のStrong parametersと今のstrong parametersの違いとかは知らないので、もしかしたらRailsので良いのかもしれません。

型はつくの?

つきます。JSONは、まあ色々あるんで any にしちゃうのが良いと思いますが、そいつからレコード型のデータ、例えば { name: String, contacts: Array[contact] } に変換すると思ってください。変換できないものはエラーになる。

一方で、この型付けが一番便利かというとそんなことはなくて「頑張れば型がつくと強弁できる」くらいの程度で、まあSteepを直さないといけないですねえ……