From 8282f645c36a1e59b4f59cd794b28c4303c97ea1 Mon Sep 17 00:00:00 2001 From: user Date: Sat, 10 Mar 2012 00:49:43 -0300 Subject: [PATCH] fixed case class type info serialization and empty case class deserialization --- .../jerkson/deser/CaseClassDeserializer.scala | 6 ++--- .../jerkson/ser/CaseClassSerializer.scala | 17 +++++++++++--- .../jerkson/tests/CaseClassSupportSpec.scala | 22 +++++++++++++++++++ .../jerkson/tests/ExampleCaseClasses.scala | 9 +++++++- 4 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/main/scala/com/codahale/jerkson/deser/CaseClassDeserializer.scala b/src/main/scala/com/codahale/jerkson/deser/CaseClassDeserializer.scala index a383419..aebc9f2 100644 --- a/src/main/scala/com/codahale/jerkson/deser/CaseClassDeserializer.scala +++ b/src/main/scala/com/codahale/jerkson/deser/CaseClassDeserializer.scala @@ -65,10 +65,10 @@ class CaseClassDeserializer(config: DeserializationConfig, values += value } + } - if (values.size == params.size) { - return constructor.newInstance(values.toArray: _*).asInstanceOf[Object] - } + if (values.size == params.size) { + return constructor.newInstance(values.toArray: _*).asInstanceOf[Object] } throw new JsonMappingException(errorMessage(node)) diff --git a/src/main/scala/com/codahale/jerkson/ser/CaseClassSerializer.scala b/src/main/scala/com/codahale/jerkson/ser/CaseClassSerializer.scala index 6e1309b..c9ab498 100644 --- a/src/main/scala/com/codahale/jerkson/ser/CaseClassSerializer.scala +++ b/src/main/scala/com/codahale/jerkson/ser/CaseClassSerializer.scala @@ -5,7 +5,7 @@ import com.codahale.jerkson.JsonSnakeCase import com.codahale.jerkson.Util._ import org.codehaus.jackson.JsonGenerator import org.codehaus.jackson.annotate.{JsonIgnore, JsonIgnoreProperties} -import org.codehaus.jackson.map.{SerializerProvider, JsonSerializer} +import org.codehaus.jackson.map.{SerializerProvider, JsonSerializer, TypeSerializer} import org.codehaus.jackson.map.annotate.JsonCachable @JsonCachable @@ -25,9 +25,20 @@ class CaseClassSerializer[A <: Product](klass: Class[_]) extends JsonSerializer[ private val methods = klass.getDeclaredMethods .filter { _.getParameterTypes.isEmpty } .map { m => m.getName -> m }.toMap - + + override def serializeWithType(value: A, json: JsonGenerator, provider: SerializerProvider, typeSerializer: TypeSerializer) { + typeSerializer.writeTypePrefixForObject(value, json) + doSerialize(value, json, provider) + typeSerializer.writeTypeSuffixForObject(value, json) + } + def serialize(value: A, json: JsonGenerator, provider: SerializerProvider) { json.writeStartObject() + doSerialize(value, json, provider) + json.writeEndObject() + } + + def doSerialize(value: A, json: JsonGenerator, provider: SerializerProvider) { for (field <- nonIgnoredFields) { val methodOpt = methods.get(field.getName) val fieldValue: Object = methodOpt.map { _.invoke(value) }.getOrElse(field.get(value)) @@ -36,6 +47,6 @@ class CaseClassSerializer[A <: Product](klass: Class[_]) extends JsonSerializer[ provider.defaultSerializeField(if (isSnakeCase) snakeCase(fieldName) else fieldName, fieldValue, json) } } - json.writeEndObject() } + } diff --git a/src/test/scala/com/codahale/jerkson/tests/CaseClassSupportSpec.scala b/src/test/scala/com/codahale/jerkson/tests/CaseClassSupportSpec.scala index 7a562f5..5d35a0c 100644 --- a/src/test/scala/com/codahale/jerkson/tests/CaseClassSupportSpec.scala +++ b/src/test/scala/com/codahale/jerkson/tests/CaseClassSupportSpec.scala @@ -236,4 +236,26 @@ class CaseClassSupportSpec extends Spec { )) } } + + class `A case class with JsonTypeInfo annotation` { + @Test def `serializes the type info to json` = { + generate(CaseClassWithTypeInfo1(1, "Coda")) must be("""{"@c":".CaseClassWithTypeInfo1","id":1,"name":"Coda"}""") + generate(CaseClassWithTypeInfo2(2, "Hale")) must be("""{"@c":".CaseClassWithTypeInfo2","id":2,"name":"Hale"}""") + } + @Test def `is parsable from a JSON object` = { + parse[WithTypeInfo]("""{"@c":".CaseClassWithTypeInfo1","id":1,"name":"Coda"}""") must be(CaseClassWithTypeInfo1(1, "Coda")) + parse[WithTypeInfo]("""{"@c":".CaseClassWithTypeInfo2","id":2,"name":"Hale"}""") must be(CaseClassWithTypeInfo2(2, "Hale")) + } + } + + class `A case class without values` { + @Test def `is parsable from an empty JSON object` = { + parse[CaseClassWithoutValues]("""{}""") must be(CaseClassWithoutValues()) + } + + @Test def `generates an empty JSON object` = { + generate(CaseClassWithoutValues()) must be("""{}""") + } + } + } diff --git a/src/test/scala/com/codahale/jerkson/tests/ExampleCaseClasses.scala b/src/test/scala/com/codahale/jerkson/tests/ExampleCaseClasses.scala index c3b666f..a27324f 100644 --- a/src/test/scala/com/codahale/jerkson/tests/ExampleCaseClasses.scala +++ b/src/test/scala/com/codahale/jerkson/tests/ExampleCaseClasses.scala @@ -1,11 +1,18 @@ package com.codahale.jerkson.tests import org.codehaus.jackson.JsonNode -import org.codehaus.jackson.annotate.{JsonIgnoreProperties, JsonIgnore} +import org.codehaus.jackson.annotate.{JsonIgnoreProperties, JsonIgnore, JsonTypeInfo} import com.codahale.jerkson.JsonSnakeCase case class CaseClass(id: Long, name: String) +case class CaseClassWithoutValues() + +@JsonTypeInfo(use=JsonTypeInfo.Id.MINIMAL_CLASS) +trait WithTypeInfo +case class CaseClassWithTypeInfo1(id: Long, name: String) extends WithTypeInfo +case class CaseClassWithTypeInfo2(id: Long, name: String) extends WithTypeInfo + case class CaseClassWithLazyVal(id: Long) { lazy val woo = "yeah" }