Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default typeHint field value #522

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@
@Target({TYPE})
public @interface JSONTypeHintField {
String value() default "type";
}
String defaultType() default "";
}
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@ package object generic extends Logging {

val fieldWithJSONTypeHint = clazz.getAnnotation(classOf[JSONTypeHintField])
val typeField = if (fieldWithJSONTypeHint != null) fieldWithJSONTypeHint.value() else defaultTypeFieldName
val defaultType = if (fieldWithJSONTypeHint != null) fieldWithJSONTypeHint.defaultType() else ""

new FromJSON[T] with TypeSelectorFromJSONContainer {
override def typeSelectors: List[TypeSelectorFromJSON[_]] = allSelectors
Expand All @@ -384,6 +385,10 @@ package object generic extends Logging {
case Some(ts) => ts.read(o).asInstanceOf[ValidatedNel[JSONError, T]]
case None => jsonParseError("Invalid type value '" + t + "' in '%s'".format(compactJson(o)))
}
case None if defaultType.nonEmpty => readMap.get(defaultType) match {
case Some(ts) => ts.read(o).asInstanceOf[ValidatedNel[JSONError, T]]
case None => jsonParseError("Invalid default type value '" + defaultType + "' in '%s'".format(compactJson(o)))
}
case None => jsonParseError("Missing type field '" + typeField + "' in '%s'".format(compactJson(o)))
}
case _ => jsonParseError("JSON object expected.")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package io.sphere.json.generic

import cats.data.Validated.Valid
import io.sphere.json._
import io.sphere.json.generic.JsonTypeHintDefaultsSpec._
import org.json4s._
import org.scalatest.matchers.must.Matchers
import org.scalatest.wordspec.AnyWordSpec

class JsonTypeHintDefaultsSpec extends AnyWordSpec with Matchers {

"JSONTypeHintField default value" must {

"fallback to default implementation when discriminator field is missing" in {
val json = """{ "addressKey": "address" }"""
getFromJSON[WithDefaultTypeField](json) must be(MissingHint("address"))
getFromJSON[WithOverridenHintField](json) must be(MissingHint2("address"))
}

"test only for default implementation when discriminator field is missing" in {
val json = """{ "shippingKey": "wrong field" }"""
a[JSONException] must be thrownBy getFromJSON[WithDefaultTypeField](json)
a[JSONException] must be thrownBy getFromJSON[WithOverridenHintField](json)
}

"ignore default type when discriminator is provided" in {
getFromJSON[WithDefaultTypeField](
"""
{
"type": "MissingHint",
"addressKey": "address"
}
""".stripMargin) must be(MissingHint("address"))
getFromJSON[WithOverridenHintField](
"""
{
"version": "old",
"addressKey": "address"
}
""".stripMargin) must be(MissingHint2("address"))
}
}
}

object JsonTypeHintDefaultsSpec {
@JSONTypeHintField(value = "type", defaultType = "MissingHint")
sealed trait WithDefaultTypeField
case class MissingHint(addressKey: String) extends WithDefaultTypeField
case class WithHint(shippingKey: String) extends WithDefaultTypeField
object WithDefaultTypeField {
implicit val json: JSON[WithDefaultTypeField] = deriveJSON[WithDefaultTypeField]
}


@JSONTypeHintField(value = "version", defaultType = "old")
sealed trait WithOverridenHintField
@JSONTypeHint("old")
case class MissingHint2(addressKey: String) extends WithOverridenHintField
@JSONTypeHint("new")
case class WithHint2(shippingKey: String) extends WithOverridenHintField
object WithOverridenHintField {
implicit val json: JSON[WithOverridenHintField] = deriveJSON[WithOverridenHintField]
}
}
Loading