aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Odersky <jakob@odersky.com>2018-08-02 15:24:52 -0700
committerJakob Odersky <jakob@odersky.com>2018-08-02 16:04:39 -0700
commit20afa757f499688b56cbd6b8571014b75d6d4dce (patch)
tree01d763e6db42e525eb71960519f5098170be9042
parenta511ec9662508f72f8ed63b08ccad41647fad9c5 (diff)
downloadspray-json-derivation-20afa757f499688b56cbd6b8571014b75d6d4dce.tar.gz
spray-json-derivation-20afa757f499688b56cbd6b8571014b75d6d4dce.tar.bz2
spray-json-derivation-20afa757f499688b56cbd6b8571014b75d6d4dce.zip
Treat value classes transparently
-rw-r--r--shared/src/main/scala/DerivedFormats.scala24
-rw-r--r--shared/src/test/scala/ProductTypeFormatTests.scala26
2 files changed, 40 insertions, 10 deletions
diff --git a/shared/src/main/scala/DerivedFormats.scala b/shared/src/main/scala/DerivedFormats.scala
index f6a3f7b..ed39f46 100644
--- a/shared/src/main/scala/DerivedFormats.scala
+++ b/shared/src/main/scala/DerivedFormats.scala
@@ -24,18 +24,24 @@ trait DerivedFormats { self: BasicFormats =>
def combine[T](ctx: CaseClass[JsonFormat, T]): JsonFormat[T] =
new JsonFormat[T] {
- override def write(value: T): JsValue = {
- val fields: Seq[(String, JsValue)] = ctx.parameters.collect {
- case param
- if !param.option || param.dereference(value) != None || printNull =>
- extractFieldName(param.label) -> param.typeclass.write(
- param.dereference(value)
- )
+ override def write(value: T): JsValue =
+ if (ctx.isValueClass) {
+ val param = ctx.parameters.head
+ param.typeclass.write(param.dereference(value))
+ } else {
+ val fields: Seq[(String, JsValue)] = ctx.parameters.collect {
+ case param
+ if !param.option || param.dereference(value) != None || printNull =>
+ extractFieldName(param.label) -> param.typeclass.write(
+ param.dereference(value)
+ )
+ }
+ JsObject(fields: _*)
}
- JsObject(fields: _*)
- }
override def read(value: JsValue): T = value match {
+ case js if ctx.isValueClass =>
+ ctx.construct(param => param.typeclass.read(value))
case obj: JsObject =>
if (ctx.isObject) {
ctx.rawConstruct(Seq.empty)
diff --git a/shared/src/test/scala/ProductTypeFormatTests.scala b/shared/src/test/scala/ProductTypeFormatTests.scala
index a869ac5..d7721ba 100644
--- a/shared/src/test/scala/ProductTypeFormatTests.scala
+++ b/shared/src/test/scala/ProductTypeFormatTests.scala
@@ -90,11 +90,35 @@ class ProductTypeFormatTests
case class Phantom[T](x: Int)
// no json format required for T
- implicit def phantom[T] = jsonFormat[Phantom[T]]
+ implicit def phantom[T]: RootJsonFormat[Phantom[T]] = jsonFormat[Phantom[T]]
"Phantom types without a format" should behave like checkRoundtrip(
Phantom[Int => String](42), // the given type parameter should not have a format
"""{"x":42}"""
)
+ implicit val vc = jsonFormat[ProductTypeFormatTests.Wrapper]
+ "Value classes" should behave like checkRoundtrip(
+ ProductTypeFormatTests.Wrapper(42),
+ """42"""
+ )
+
+ implicit def vcg[T: JsonFormat] = jsonFormat[ProductTypeFormatTests.WrapperGeneric[T]]
+ "Value classes with generic parameters" should behave like checkRoundtrip(
+ ProductTypeFormatTests.WrapperGeneric[F](F(42)),
+ """{"y": 42}"""
+ )
+
+ implicit def vcp[T] = jsonFormat[ProductTypeFormatTests.WrapperPhantom[T]]
+ "value classes with unused generic parameters" should behave like checkRoundtrip(
+ ProductTypeFormatTests.WrapperPhantom[Int => String](42),
+ """42"""
+ )
+
+}
+
+object ProductTypeFormatTests {
+ case class Wrapper(x: Int) extends AnyVal
+ case class WrapperGeneric[A](x: A) extends AnyVal
+ case class WrapperPhantom[A](x: Int) extends AnyVal
}