トップ «前の日記(2010-08-17) 最新 次の日記(2010-09-03)» 編集

Ussy Diary


2010-08-22

[Scala][Json]SJSON でオブジェクトを JSON 形式にシリアライズする

[追記]

scala-tools リポジトリに登録されています。

http://scala-tools.org/repo-releases/net/debasishg/sjson_2.8.0/

[/追記]

Java の Json ライブラリは Scala の Map, List などに対応していないので、 Pure Scala オブジェクトではシリアライズできません。

Scala 向けに SJSON というライブラリが公開されていて、リフレクション、型変換によるシリアライズがサポートされています。今回はこのライブラリを使って 2.8 ベースでリフレクションによるシリアライズを試してみました。

SJSON は SBT のみサポートされていますが、 Akka プロジェクトが maven リポジトリで公開してくれているので、そちらのリポジトリを参照するようにしておきます。またライブラリ内部ではさらに dispatch ライブラリを利用していますので、そちらも参照します。

pom.xml

SJSON が登録されているリポジトリを登録します。

<repository>
  <id>akka.repository</id>
  <url>http://scalablesolutions.se/akka/repository</url>
</repository>

dispatch が登録されているリポジトリを登録します。

<repository>
  <id>scala-tools.org</id>
  <url>http://scala-tools.org/repo-releases</url>
</repository>

ライブラリの依存関係を書いておきます。

<dependency>
  <groupId>sjson.json</groupId>
  <artifactId>sjson</artifactId>
  <version>0.7-2.8.0</version>
</dependency>
<dependency>
  <groupId>net.databinder</groupId>
  <artifactId>dispatch-json_2.8.0</artifactId>
  <version>0.7.5</version>
</dependency>

ライブラリを取り込んだらシリアライズするだけなのですが、 JSON に変換できるクラスにするには条件があります。

  • @BeanInfo を指定する
  • case class にする

下のようにクラスを定義しておきます。

import scala.reflect.BeanInfo
@BeanInfo case class Person(name: String, fav: Map[String, String])

定義ができたら SJSON#out でシリアライズできます。

import sjson.json.Serializer.SJSON
SJSON.out(Person("ussy", Map("1" -> "Scala", "2" -> "Ruby")))

SJSON#out は byte 配列で返してくるので

new String(SJSON.out(Person("ussy", Map("1" -> "Scala", "2" -> "Ruby"))))

とすると JSON 文字列が返ってきます。

{"fav":{"1":"Scala","2":"Ruby"},"name":"ussy"}

内部で JSON 文字列に変換したあとに、 getBytes("UTF-8") してくれているのですが、 JSON 文字列をただ返してくれるものがあってもいいような感じがしますね。

そんなわけで Java では Gson や JSONIC が有名ですが、 Scala では今のところ SJSON がいい感じです。