play2でのJsonの取り扱い

| Comments

json ↔ scalaObjectの変換が上手く行かないのでメモ(解決してない。)

したいこと

redisなどのキャッシュサーバにデータを格納しておくとき、Scalaのオブジェクトを文字列にして格納しておきたい。

で、取ってくるときにはその文字列をオブジェクトに再変換したい。

ざっくりとした例

Playについてるjsonライブラリを使う。

JsValueは、json文字列をパースした状態のオブジェクト。(ASTとか構文木って言うのかな。。よく知らない。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import play.api.libs.json.{JsValue, Json}

object PlayJson {

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

	implicit val writes = Json.writes[Person]
	implicit val reads = Json.reads[Person]

	val person = Person(1,"shiba")

	//ScalaObject => jsonString
	val jsValue1: JsValue = Json.toJson(person)
	val str:String = Json.stringify(jsValue1)

	//ScalaObject <= jsonString
	val jsValue2:JsValue = Json.parse(str)
	val person2:Person = Json.fromJson[Person](jsValue2).asOpt.get

}

型を細かく書いてるのでやりたいことはわかると思う。

結果

こんな感じで変換できるはず、、、なのだが、実際にWebアプリケーションで似たことをするとたまに(3割くらいで)変換に失敗する。

この「たまに」ってのが非常にウザい。。。

ちなみに、エラーの発生箇所は、JsValueから某Objectへの変換のところらしい。(たま〜にJsValueへの変換でもミスってる)

原因として思い当たるのは、

  • 文字列の格納にredisを使ってて、そこで文字列が改変される。
  • 某ObjectがList[HogeObject]とかになってるせい。
  • Jsonとのマッピングをちゃんと定義してないせい

たぶんどれもがちょっとずつ関与してるんだろうな、という感じで困っている。

解決案

JsValueと某Objectのマッピングを丁寧に書いてあげる。(まだ試してない。)

Comments