diff options
author | Jakob Odersky <jakob@odersky.com> | 2018-02-14 15:00:52 -0800 |
---|---|---|
committer | Jakob Odersky <jakob@odersky.com> | 2018-02-14 15:00:52 -0800 |
commit | 7ab0889d7ab4480d0d90346432006ffd345b4916 (patch) | |
tree | fccce4902dfc4241a651dfac32e4ef77288de3c9 /src/main/scala/DerivedFormats.scala | |
parent | 5a37bfee89a2b5ae17c7980327a92c381c006cf7 (diff) | |
download | spray-json-derivation-7ab0889d7ab4480d0d90346432006ffd345b4916.tar.gz spray-json-derivation-7ab0889d7ab4480d0d90346432006ffd345b4916.tar.bz2 spray-json-derivation-7ab0889d7ab4480d0d90346432006ffd345b4916.zip |
Remove need for special case for enums
Diffstat (limited to 'src/main/scala/DerivedFormats.scala')
-rw-r--r-- | src/main/scala/DerivedFormats.scala | 86 |
1 files changed, 34 insertions, 52 deletions
diff --git a/src/main/scala/DerivedFormats.scala b/src/main/scala/DerivedFormats.scala index 08c452c..4fc096e 100644 --- a/src/main/scala/DerivedFormats.scala +++ b/src/main/scala/DerivedFormats.scala @@ -27,7 +27,7 @@ trait DerivedFormats { self: BasicFormats => ctx.construct { param => param.typeclass.read(obj.fields(param.label)) } - case str: JsString if ctx.isObject && str.value == ctx.typeName.short => + case JsString(str) if ctx.isObject && str == ctx.typeName.short => ctx.rawConstruct(Seq.empty) case js => @@ -36,64 +36,46 @@ trait DerivedFormats { self: BasicFormats => } } - def dispatch[T](ctx: SealedTrait[JsonFormat, T]): JsonFormat[T] = - new JsonFormat[T] { - def tpe = - ctx.annotations - .find(_.isInstanceOf[JsonAnnotation]) - .getOrElse(new gadt("type")) - - override def write(value: T): JsValue = tpe match { - case _: enum => - ctx.dispatch(value) { sub => - JsString(sub.typeName.short) - } + def dispatch[T](ctx: SealedTrait[JsonFormat, T]): JsonFormat[T] = { + val typeFieldName = ctx.annotations + .collectFirst{ + case g: gadt => g.typeFieldName + } + .getOrElse("type") - case g: gadt => - ctx.dispatch(value) { sub => - val obj = sub.typeclass.write(sub.cast(value)).asJsObject + new JsonFormat[T] { + override def write(value: T): JsValue = ctx.dispatch(value) { sub => + sub.typeclass.write(sub.cast(value)) match { + case obj: JsObject => JsObject( - (Map(g.typeFieldName -> JsString(sub.typeName.short)) ++ + (Map(typeFieldName -> JsString(sub.typeName.short)) ++ obj.fields).toSeq: _*) - } + case js => js + } } - override def read(value: JsValue): T = tpe match { - case _: enum => - value match { - case str: JsString => - ctx.subtypes - .find(_.typeName.short == str.value) - .getOrElse(deserializationError( - s"Cannot deserialize JSON to ${ctx.typeName.full} because " + - "type '${str}' has an unsupported value.")) - .typeclass - .read(str) - case js => - deserializationError( - s"Cannot read JSON '$js' as a ${ctx.typeName.full}") - } - - case g: gadt => - value match { - case obj: JsObject if obj.fields.contains(g.typeFieldName) => - val fieldName = obj.fields(g.typeFieldName).convertTo[String] - - ctx.subtypes.find(_.typeName.short == fieldName) match { - case Some(tpe) => tpe.typeclass.read(obj) - case None => - deserializationError( - s"Cannot deserialize JSON to ${ctx.typeName.full} " + - s"because type field '${fieldName}' has an unsupported " + - "value.") - } + override def read(js: JsValue): T = { + val typeName: String = js match { + case obj: JsObject if obj.fields.contains(typeFieldName) => + obj.fields(typeFieldName).convertTo[String] + case JsString(str) => + str + case _ => + deserializationError( + s"Cannot deserialize JSON to ${ctx.typeName.full} " + + "because serialized type cannot be determined.") + } - case js => - deserializationError( - s"Cannot read JSON '$js' as a ${ctx.typeName}") - } + ctx.subtypes.find(_.typeName.short == typeName) match { + case Some(tpe) => tpe.typeclass.read(js) + case None => + deserializationError( + s"Cannot deserialize JSON to ${ctx.typeName.full} " + + s"because type '${typeName}' is unsupported.") + } } - } + } + } implicit def gen[T]: JsonFormat[T] = macro Magnolia.gen[T] |