Scala の JSON.parseFull で Int値が自動的にDouble値になる件

2014.04.23 追記
scala.util.parsing.json.JSON を使わずに他のライブラリを使おう!
Json4s を使ってみた - kakakakakku blog

背景

ScalaJSON をパースするときに標準で入ってる scala.util.parsing.json.JSON オブジェクトの parseFull を使うと,Int値が自動的にDouble値になるみたいなので調べてみたところ,仕様だったって話.

デフォルトで使ってみる

Int値とDouble値をもった JSON をパースすると Option[Any] で返ってきて,Int値が 10000.0 になってしまう.

import scala.util.parsing.json.JSON
object MyJsonParser extends App {
  val json = """{"name": "kakakakakku", "intval": 10000, "doubleval": 1234.5}"""
  println(JSON.parseFull(json))
}
Some(Map(name -> kakakakakku, intval -> 10000.0, doubleval -> 1234.5))

Scaladoc を見てみた

Scala Standard Library API (Scaladoc) 2.10.4 を見てみると,The default conversion for numerics is into a double. と書いてあって,カスタマイズしたかったら globalNumberParser をオーバライドしてと書いてあった.

This object provides a simple interface to the JSON parser class. The default conversion for numerics is into a double. If you wish to override this behavior at the global level, you can set the globalNumberParser property to your own (String => Any) function. If you only want to override at the per-thread level then you can set the perThreadNumberParser property to your function.

globalNumberParser をオーバライドする

globalNumberParser をオーバライドして実行してみると,同じく Option[Any] で返ってきて,Int値は 10000 になる.これで使える感じになった.

import scala.util.parsing.json.JSON
object MyJsonParser extends App {
  val json = """{"name": "kakakakakku", "intval": 10000, "doubleval": 1234.5}"""
  JSON.globalNumberParser = { input => try { input.toInt } catch { case e => input.toDouble } }
  println(JSON.parseFull(json))
}
Some(Map(name -> kakakakakku, intval -> 10000, doubleval -> 1234.5))

ちなみに,JSON にDouble値が入らないことが前提になってるような場合であれば,以下の書き方でも良いけど,もしDouble値が入ってると java.lang.NumberFormatException が出るので注意すること.

JSON.globalNumberParser = { input => Integer.parseInt(input) }

関連エントリー

Usage of globalNumberParser of scala.util.parsing.json.JSON
Is it possible to make Scala's JSON.parseFull() not to treat Integers as Decimals? - Stack Overflow
xawa雑記帳: [Scala] JSON の扱い
xawa雑記帳: [Scala] JSON の標準パーサーで数値型が Double になる問題への対処方法