しいしせねっと
[Java] [ABNF]

JSONを実装してみる

概要

WebのAPIでよく使われるようになったJSON、もともとJavaScriptのデータ形式だったようなものがいろいろあってRESTなどでXMLに代わるデータ形式として定着、RFC 8259などで標準化されている。

JSONにたどり着くには

JavaでJSONを扱うには、JavaのCollection系やオブジェクトと相互変換できると便利です。

JSON for Java標準的なAPIもあるようですが、GSON、Jacksonなどが有名なようです。とりあえずどちらも知らないので使わない(謎)

JSONの延長線上には

などいろいろありますが、それは略。REST方面へ続ける。

JavaでRESTを扱うのは、JAX-RSかJAX-WSか、また別のものです。

作る過程

バイト列から切り取る方法でJSONパーサを作ってしまいます。

RFCに仕様があるのでParserを作るのも簡単、いくつか作ってみたというものもあるようなので、ここでもParserを作ってみますがJSON Parserは書きません。

JSONを実装するにはABNF構文を使って解析していくことが必要なため、まず最初にABNFを作ります。

RFCで使われている記述方式で、今回これもSoftLibABNFとして実装したので[ABNF]別途解説。JSON以外のものも楽々実装できる形に仕上がってしまいました。

本来この過程は構文解析などを使ったり書いたりするようなのですが、ABNFで構文解析をするという変な方向から攻めたので手間はABNFの方に封入してしまいました。JSON自体は構文解析の手間がほとんどありません。

JSONのABNF構文をさらっと通し、JSONの要素をJavaのオブジェクトに対応させていくだけでほぼ完成です。エスケープの処理などが多少複雑になったりしますが最新のJSONはUTF-8のみなのでいろいろ楽です。

分解して生成された要素を組み立てていくだけでJSONをJavaのMapやListで構成したJavaオブジェクト化が可能です。パースエラー生成は苦手です。

JSON Pointer, JSON Patchなども実装してみたあたりで JSON for Java(JSONP)と比較してみたところ、ほぼ似たような構成なので寄せてみることに。jsonでは統合してみましたがjson2では分離してJSONPも実装しています。

Object MappingとあわせてJavaのどのあたりの要素に関連づけるかいろいろ試行錯誤しましたが、最終的に一度低いところに置くことで落ち着きました。net.siisise.json と net.siisise.json2 と2系統あるので最終的には2の方を使う予定です。2の系統ではJSONPとObject Mappingを整理し本体から分離できました。

こんな感じの仕上がりでオブジェクトマッピングも柔軟に相互変換可能かもしれない構造に仕上げます。

そこからObjectやBeanにマッピングしていくことで、JavaとJSONのオブジェクトの変換的なものが実現します。プリミティブ型、配列、class、CollectionとJSONをどのように対応づけるかは好みによるところかもしれません。

というわけで2系に統合してしまいました。JSONPの系譜もやや拡張する程度で対応します。

JSONを吐き出すところをObject Mapping の流れにリファクタリングすると、いろいろ拡張性が広がったので、Jakarta JSON系の対応まで進めます。

Object Mapping を別のパッケージにまとめ、Jakarta JSONなところも分離。CBOR、YAMLなどの対応もはじめてみます。

 

SottLibJSONのご紹介

SoftLibJSONは、基本的にはJSONのParserとオブジェクトマッピング関連の強化ライブラリです。ABNFのParserをつついていてできた副産物のようなものです。

依存ライブラリ

基本的にJava 8標準とJSON系API, 自家製ライブラリ(SoftLib,SoftLibABNF,SoftLibRebind)のみ利用しています。Apacheなどのライブラリは不要です。

最近はオブジェクトマッピング機能をつついているのでそちら方面はお得です。