aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Odersky <jakob@driver.xyz>2018-06-29 17:56:06 -0700
committerJakob Odersky <jakob@odersky.com>2018-06-30 00:32:44 -0700
commitc4dd18f810afdb4adb85d002ad34e660fe54c146 (patch)
treedc2c3b8f51009a96c9be7cd5831e8ce3280caa6b
parent9545fe93dfe68974ca4bf2f9e6310216fc914e15 (diff)
downloadspray-json-derivation-c4dd18f810afdb4adb85d002ad34e660fe54c146.tar.gz
spray-json-derivation-c4dd18f810afdb4adb85d002ad34e660fe54c146.tar.bz2
spray-json-derivation-c4dd18f810afdb4adb85d002ad34e660fe54c146.zip
Fix bug in derivation of classes with type parametersv0.4.6
-rwxr-xr-x.ci/build2
-rw-r--r--CHANGELOG.md15
-rw-r--r--project/plugins.sbt2
-rw-r--r--shared/src/main/scala/DerivedFormats.scala17
-rw-r--r--shared/src/main/scala/annotations.scala6
-rw-r--r--shared/src/test/scala/CoproductTypeFormatTests.scala3
-rw-r--r--shared/src/test/scala/ProductTypeFormatTests.scala24
7 files changed, 57 insertions, 12 deletions
diff --git a/.ci/build b/.ci/build
index 1c8e832..3354e1a 100755
--- a/.ci/build
+++ b/.ci/build
@@ -2,7 +2,7 @@
set -ev
sbt \
- scalafmtTest \
+ scalafmtCheck \
+sprayJsonDerivationJVM/mimaReportBinaryIssues \
+test
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fa2f894..de43491 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,18 @@
+# Version 0.4.6
+
+- Fix a bug in the derivation macro that prevented deriving formats for
+ parameterized types. I.e. it is now possible to write derive the following:
+ ```
+ class A[B](b: B)
+ implicit def fmt[B: JsonFormat] = jsonFormat[A]
+ ```
+
+- Formatting and documentation tweaks
+
+# Version 0.4.5
+
+Fixes an issue in when serializing field names with an alternate case.
+
# Version 0.4.4
- Add utility mixins to change serialization of fieldnames, such as
diff --git a/project/plugins.sbt b/project/plugins.sbt
index d983863..67c3649 100644
--- a/project/plugins.sbt
+++ b/project/plugins.sbt
@@ -1,6 +1,6 @@
ivyLoggingLevel := UpdateLogging.Quiet
-addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "1.2.0")
+addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "1.6.0-RC3")
addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "0.1.18")
addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "0.4.0")
addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "0.4.0")
diff --git a/shared/src/main/scala/DerivedFormats.scala b/shared/src/main/scala/DerivedFormats.scala
index 03e632f..6ea7c4b 100644
--- a/shared/src/main/scala/DerivedFormats.scala
+++ b/shared/src/main/scala/DerivedFormats.scala
@@ -18,7 +18,8 @@ trait DerivedFormats { self: BasicFormats =>
override def write(value: T): JsValue = {
val fields: Seq[(String, JsValue)] = ctx.parameters.map { param =>
extractFieldName(param.label) -> param.typeclass.write(
- param.dereference(value))
+ param.dereference(value)
+ )
}
JsObject(fields: _*)
}
@@ -40,7 +41,8 @@ trait DerivedFormats { self: BasicFormats =>
}
case js =>
deserializationError(
- s"Cannot read JSON '$js' as a ${ctx.typeName.full}")
+ s"Cannot read JSON '$js' as a ${ctx.typeName.full}"
+ )
}
}
@@ -57,7 +59,8 @@ trait DerivedFormats { self: BasicFormats =>
case obj: JsObject =>
JsObject(
(Map(typeFieldName -> JsString(sub.typeName.short)) ++
- obj.fields).toSeq: _*)
+ obj.fields).toSeq: _*
+ )
case js => js
}
}
@@ -71,7 +74,8 @@ trait DerivedFormats { self: BasicFormats =>
case _ =>
deserializationError(
s"Cannot deserialize JSON to ${ctx.typeName.full} " +
- "because serialized type cannot be determined.")
+ "because serialized type cannot be determined."
+ )
}
ctx.subtypes.find(_.typeName.short == typeName) match {
@@ -79,7 +83,8 @@ trait DerivedFormats { self: BasicFormats =>
case None =>
deserializationError(
s"Cannot deserialize JSON to ${ctx.typeName.full} " +
- s"because type '${typeName}' is unsupported.")
+ s"because type '${typeName}' is unsupported."
+ )
}
}
}
@@ -117,7 +122,7 @@ object DerivedFormatMacros {
/** Utility that converts a magnolia-generated JsonFormat to a RootJsonFormat. */
def derivedFormat[T: c.WeakTypeTag](c: Context): c.Tree = {
import c.universe._
- val tpe = weakTypeOf[T].typeSymbol.asType
+ val tpe = weakTypeOf[T]
val sprayPkg = c.mirror.staticPackage("spray.json")
val valName = TermName(c.freshName("format"))
q"""{
diff --git a/shared/src/main/scala/annotations.scala b/shared/src/main/scala/annotations.scala
index 9d35d16..1b7c62c 100644
--- a/shared/src/main/scala/annotations.scala
+++ b/shared/src/main/scala/annotations.scala
@@ -3,13 +3,13 @@ package spray.json
import scala.annotation.StaticAnnotation
/** An annotation that designates that a sealed trait is a generalized algebraic
- * datatype (GADT), and that a type field containing the serialized childrens'
- * types should be added to the final JSON objects.
+ * datatype (GADT), and that a field containing the serialized childrens' types
+ * should be added to the final JSON objects.
*
* Note that by default all sealed traits are treated as GADTs, with a type
* field called `type`. This annotation enables overriding the name of that
* field and is really only useful if a child itself has a field called `type`
- * that would result in a conflict.
+ * that would otherwise result in a conflict.
*
* Example:
* {{{
diff --git a/shared/src/test/scala/CoproductTypeFormatTests.scala b/shared/src/test/scala/CoproductTypeFormatTests.scala
index de73967..cd6a2ae 100644
--- a/shared/src/test/scala/CoproductTypeFormatTests.scala
+++ b/shared/src/test/scala/CoproductTypeFormatTests.scala
@@ -54,7 +54,8 @@ class CoproductTypeFormatTests
implicit val crazyFormat: RootJsonFormat[Crazy] = jsonFormat[Crazy]
"GADT with special characters in type field" should behave like checkRoundtrip[
- Crazy](
+ Crazy
+ ](
CrazyType(),
"""{"_`crazy type!`\"": "CrazyType"}"""
)
diff --git a/shared/src/test/scala/ProductTypeFormatTests.scala b/shared/src/test/scala/ProductTypeFormatTests.scala
index 4d71aa3..4c979c0 100644
--- a/shared/src/test/scala/ProductTypeFormatTests.scala
+++ b/shared/src/test/scala/ProductTypeFormatTests.scala
@@ -90,4 +90,28 @@ class ProductTypeFormatTests
assert("{}".parseJson.convertTo[Opt] == Opt(None))
}
+ case class Typed[T](t: T)
+
+ implicit def typed[T: JsonFormat] = jsonFormat[Typed[T]]
+
+ "Class with a type parameter" should behave like checkRoundtrip(
+ Typed[Int](42),
+ """{"t":42}"""
+ )
+
+ "Class with nested types" should behave like checkRoundtrip(
+ Typed[Typed[String]](Typed("hello world")),
+ """{"t":{"t":"hello world"}}"""
+ )
+
+ case class Phantom[T](x: Int)
+
+ // no json format required for T
+ implicit def 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}"""
+ )
+
}