値クラスを使っていて不可解な挙動があったので、まとめたのとその対処法をメモしておきます。
値クラスとは
値クラスとはIntやStringが継承しているAnyValを継承させたクラスです。
一つの値しか持ちませんが拡張メソッドを実装できるため、DDDなどを実現するためのドメインモデルの記述に役立つ記法です。
値クラスと汎用トレイト - Scala Documentation
問題
コンパイル時の型は統一されていますが、実行時の型が不定という問題。
上のように、コンパイル時の内部で保持している型は共にAttributesクラス(値クラス)なのですが、
実際に実行してみると、
- json4sから流し込んだ方:String型で保持
- 値クラスをそのままセット:Attributesクラスで保持
ということで、非常に不便な状況です。
対処法
対処法に関しては、単純にjson4sから流し込む部分は全てStringで受け、値クラスの方にはそのままセットするように作成しました。
まとめ
結局、Scala側の仕様なのかバグなのかよくわかりません。
元々値クラス自体、実行時に内部で保持している型を利用するという仕様なので使いやすいのですが、その評価がjson4sによっておかしくなるということでしょうか?
実行時の型が不安定というのは開発者としては、結構使いづらいのでそこの解決はお願いしたいですね。。
追記
このブログ公開後、速攻でお返事頂いたので、記載いたします。
結論json4sのバグのようでした。
@moc_yuto json4sのバグだと思います。json4sは、短く書ける反面、非公式なAPIに依存して黒魔術をしてる(?)ので値class以外にもそういう罠が超大量にある(type alasなどでも)ので、json4s自体やめるか、value classやめたほうがいいです
— Kenji Yoshida (@xuwei_k) 2016年10月10日
黒魔術なリフレクションAPI使ってるので、値class、type alias、default引数、traitなどJavaにはないScala独自の機能がどうclassファイルにエンコードされてか?の大体を把握しないと完璧にならないし、そんなのを全部メンテできる(したい)コミッターは
— Kenji Yoshida (@xuwei_k) 2016年10月10日
いないので、issueはどんどん溜まっていくばかりだし、他の方法で同じ目的を大体達成している他のjsonライブラリ最近は大量にあるのに、今どきjson4s使う積極的な理由ないので、みなさんjson4s使うのやめよう
— Kenji Yoshida (@xuwei_k) 2016年10月10日
(blogじゃなくtweetで済ませた)