Magnolia Tech

いつもコードのことばかり考えている人のために。

Json4sの使い方

前回のエントリからの続き。今回はざっとJson4sの使い方をおさらいする。

JSON文字列のパースと、生成

Json4sはバックエンドとしてJavaJSONライブラリであるJacksonを使うjacksonパッケージと、lift-json由来のパーサーを提供するnativeパッケージの2種類が用意されていて、どちらを使うかによってimportするパッケージが変わってくる。

例えばjacksonパッケージを使ってJSONをパースし、指定したデータ型にマッピングするときは、以下のようなコードとなる。

import org.json4s._
import org.json4s.jackson.Serialization
import org.json4s.jackson.Serialization.read

implicit val formats = Serialization.formats(NoTypeHints)

case class Person(name: String, age: Int)

val p = read[Person]("""{"name": "John", "age": 42 }""") # -> Person(John,42)

逆に、ScalaのデータからJSON文字列を生成する場合は、以下のようなコードとなる。

import org.json4s._
import org.json4s.jackson.Serialization
import org.json4s.jackson.Serialization.write

implicit val formats = Serialization.formats(NoTypeHints)

case class Person(name: String, age: Int)

val p = Person("John", 42)
val j = write(p) # -> {"name":"John","age":42}

上記の例ではjacksonパッケージを使ったが、nativeパッケージでも同様に動作する。

ただし、Jacksonのパーサーは頻繁にメンテナンスが行われているが、Json4sのパッケージ内でメンテナンスされているnative版パーサーは現在では決してきちんとメンテナンスされているとは言いがたく、不正なJSON文字列でもパースできてしまったり、RFC8259で定義されているobjectやarray以外のトップレベルのデータを正しくパースできないといった問題が有り、今ではJackson版を使っておく方が安全である。

JSON ASTを経由する

先ほどの例では直接JSON文字列をScalaのcase classにマッピングしたが、内部では一回JSON ASTを経由している。

次はJSON ASTを明示的に生成する方法を紹介する。

JSON文字列からJSON ASTを生成するためにはparseメソッドを使用する。

import org.json4s._
import org.json4s.jackson.JsonMethods._

val pa = parse("""{"name":"John","age":42}""") # -> JObject(List((name,JString(John)), (age,JInt(42))))

反対に、JSON ASTからJSON文字列を生成するためには、prettyメソッドか、compactメソッドを利用する。

val p = pretty(pa)

# {
#   "name" : "John",
#   "age" : 42
# }

val c = compact(pa)
# {"name":"John","age":42}

JSON ASTを経由する理由は、Json4sにはASTを直接操作するための豊富なメソッド(filterやmerge、query構文)が用意されていて、JSONをそのままScalaのデータ型にマッピングする前に一定の前処理をしておきたい、といった場合に有効である。詳しくはREADMEを参照のこと。

元々Json4sはScalaJSONライブラリに共通的に利用可能はASTを提供するために作られた経緯があり、豊富なASTレベルでの操作メソッドが用意されている。

おわりに

Json4sが用意するJSON ASTを操作するためのメソッド群は非常にたくさんの種類が用意されていますが、冒頭の例のように直接Scalaのデータ型にマッピングした方が扱いやすいと思いますので、まずはJSONScalaのデータ型を変換するorg.json4s.jackson.Serializationパッケージの使い方を覚えれば十分です。

次回は、JSON ASTからScalaのデータ型へ変換する方法について解説します。Json4sがランタイムリフレクションを使いまくっている様子をご紹介します。