diff --git a/src/main/scala/sjson/json/JsBean.scala b/src/main/scala/sjson/json/JsBean.scala index 2c5f609..cdfea55 100644 --- a/src/main/scala/sjson/json/JsBean.scala +++ b/src/main/scala/sjson/json/JsBean.scala @@ -249,10 +249,12 @@ trait JsBean { if (y.getType.isAssignableFrom(classOf[scala.Option[_]])) { // handle None case which comes as an empty List since we serialize None as [] if (num.isInstanceOf[List[_]] && num.asInstanceOf[List[_]].isEmpty) y.set(instance, None) + else if (num.isInstanceOf[BigDecimal]) { + val inner = getInnerTypeForOption(y.getType, y) + y.set(instance, Some(mkNum(num, inner))) + } else y.set(instance, Some(num)) - } else { - y.set(instance, num) - } + } else y.set(instance, num) } } } diff --git a/src/main/scala/sjson/json/Serializer.scala b/src/main/scala/sjson/json/Serializer.scala index c8353dd..fc355b4 100644 --- a/src/main/scala/sjson/json/Serializer.scala +++ b/src/main/scala/sjson/json/Serializer.scala @@ -46,7 +46,7 @@ object Serializer { in[T](Js(json)) // (m) } - private[json] def in[T: Manifest](js: JsValue): T = { + def in[T: Manifest](js: JsValue): T = { val m = implicitly[Manifest[T]] // Map and Tuple2 both are serialized as Maps wrapped within a JsObject if (m.erasure == classOf[collection.immutable.Map[_, _]] || diff --git a/src/main/scala/sjson/json/Util.scala b/src/main/scala/sjson/json/Util.scala index fbe27e6..e47c7fa 100644 --- a/src/main/scala/sjson/json/Util.scala +++ b/src/main/scala/sjson/json/Util.scala @@ -47,13 +47,17 @@ object Util { str.toString } - def mkNum(v: BigDecimal, c: Class[_]): Any = { - if (c.isAssignableFrom(classOf[Int])) v.asInstanceOf[BigDecimal].intValue - else if (c.isAssignableFrom(classOf[Long])) v.asInstanceOf[BigDecimal].longValue - else if (c.isAssignableFrom(classOf[Float])) v.asInstanceOf[BigDecimal].floatValue - else if (c.isAssignableFrom(classOf[Double])) v.asInstanceOf[BigDecimal].doubleValue - else if (c.isAssignableFrom(classOf[Short])) v.asInstanceOf[BigDecimal].shortValue - else v + def mkNum(v: Any, c: Class[_]) = { + v match { + case b: BigDecimal => + if (c.isAssignableFrom(classOf[Int])) b.intValue + else if (c.isAssignableFrom(classOf[Long])) b.longValue + else if (c.isAssignableFrom(classOf[Float])) b.floatValue + else if (c.isAssignableFrom(classOf[Double])) b.doubleValue + else if (c.isAssignableFrom(classOf[Short])) b.shortValue + else b + case _ => sys.error("unexpected") + } } import java.util.Date diff --git a/src/test/scala/sjson/json/JsonSpec.scala b/src/test/scala/sjson/json/JsonSpec.scala index caa75e0..7dbf73d 100644 --- a/src/test/scala/sjson/json/JsonSpec.scala +++ b/src/test/scala/sjson/json/JsonSpec.scala @@ -497,6 +497,17 @@ class JsonSpec extends Spec with ShouldMatchers { val o2 = jsBean.fromJSON(Js(json2), Some(classOf[DesignDocument])).asInstanceOf[DesignDocument] o2.validate_doc_update.isDefined should equal(false) } + + it("should process optional shows correctly") { + val all_pass = "function(newDoc, oldDoc, userCtx) {}" // all valid + val summary = "function(doc, rec) {}" + val detail = "function(doc, rec) {}" + val bar = "function(head, rec) {}" + val zoom = "function(head, rec) {}" + val d1 = DesignDocument("foo_valid", null, Map[String, View](), Some(all_pass), Some(Map("summary" -> summary, "detail" -> detail)), Some(Map("zoom" -> zoom, "bar" -> bar))) + val json1 = jsBean.toJSON(d1) + println(json1) + } } } diff --git a/src/test/scala/sjson/json/SerializerSpec.scala b/src/test/scala/sjson/json/SerializerSpec.scala index 55a76de..4f71ffc 100644 --- a/src/test/scala/sjson/json/SerializerSpec.scala +++ b/src/test/scala/sjson/json/SerializerSpec.scala @@ -371,4 +371,11 @@ class SerializerSpec extends Spec with ShouldMatchers { serializer.in[List[List[Address]]](serializer.out(l)) should equal(l) } } + + describe("Serialization of Long in a bean") { + it("should serialize") { + val m = Manager("alexander", Some(27l)) + serializer.in[Manager](serializer.out(m)) should equal(m) + } + } } diff --git a/src/test/scala/sjson/json/TestBeans.scala b/src/test/scala/sjson/json/TestBeans.scala index f574cb5..0fc52a9 100644 --- a/src/test/scala/sjson/json/TestBeans.scala +++ b/src/test/scala/sjson/json/TestBeans.scala @@ -317,12 +317,20 @@ object TestBeans { def this() = this (Some("default"), List[String]()) } + @BeanInfo + case class Manager(name: String, + @(OptionTypeHint@field)(value = classOf[Long]) age: Option[Long]) { + private def this() = this ("", None) + } + @BeanInfo case class DesignDocument(var _id: String, @(JSONProperty @getter)(ignoreIfNull = true, ignore = false) _rev: String, @(JSONTypeHint @field)(value = classOf[View]) views: Map[String, View], - @(JSONProperty @getter)(ignoreIfNull = true, ignore = false) validate_doc_update: Option[String] = None) { - private def this() = this(null, null, Map[String, View](), None) + @(JSONProperty @getter)(ignoreIfNull = true, ignore = false) validate_doc_update: Option[String] = None, + @(JSONProperty @getter)(ignoreIfNull = true, ignore = false) shows: Option[Map[String, String]] = None, + @(JSONProperty @getter)(ignoreIfNull = true, ignore = false) lists: Option[Map[String, String]] = None) { + private def this() = this(null, null, Map[String, View]()) override def toString = { "_id = " + _id + " _rev = " + _rev + " " + " validate = " + validate_doc_update +