Skip to content

Instantly share code, notes, and snippets.

@TylerPachal
Last active June 27, 2017 15:18
Show Gist options
  • Save TylerPachal/6e738025b9e14316d41ef6a24cb44ff1 to your computer and use it in GitHub Desktop.
Save TylerPachal/6e738025b9e14316d41ef6a24cb44ff1 to your computer and use it in GitHub Desktop.
An example of how to express (positive) Infinite in JSON using Play!
// This is an example of how to express Infinity in Json using the Play! Scala Json library.
// Infinity cannot be expressed as a Scalar value in Json, so I am using an object to hold it instead.
//
// Example of a finite value:
// {
// "value": 12.009,
// "isInfinite": false
// }
//
// Example of an infinite value:
// {
// "value": null,
// "isInfinite": true
// }
//
// It should be used as any other reads, for example:
// jsonPayload.as[PossiblyInfinite]
case class PossiblyInfinite(value: Double) {
val isInfinite: Boolean = value.isInfinite
}
object PossiblyInfinite {
def Infinite: PossiblyInfinite = PossiblyInfinite(Double.PositiveInfinity)
private val VALUE_KEY = "value"
private val IS_INFINITE_KEY = "isInfinite"
implicit val writes: Writes[PossiblyInfinite] = new Writes[PossiblyInfinite] {
override def writes(o: PossiblyInfinite): JsValue = {
if (o.isInfinite) {
Json.obj(VALUE_KEY -> JsNull, IS_INFINITE_KEY -> true)
} else {
Json.obj(VALUE_KEY -> o.value, IS_INFINITE_KEY -> false)
}
}
}
implicit object PossiblyInfiniteReads extends Reads[PossiblyInfinite] {
override def reads(json: JsValue): JsResult[PossiblyInfinite] = {
val maybeDouble = json.asOpt[Double]
lazy val maybeValue = (json \ VALUE_KEY).asOpt[Double]
lazy val maybeIsInfinite = (json \ IS_INFINITE_KEY).asOpt[Boolean]
// If this was a scalar double, use its value
if (maybeDouble.isDefined) {
JsSuccess(PossiblyInfinite(maybeDouble.get))
}
// If it wasn't a scalar double, check the other properties
else {
(maybeValue, maybeIsInfinite) match {
// Case 1: value is defined (it can't be Infinite here because JSON doesn't allow it)
case (Some(value), _) => JsSuccess(PossiblyInfinite(value))
// Case 2: isInfinite is true
case (_, Some(true)) => JsSuccess(PossiblyInfinite.Infinite)
// Case 3: there isn't enough information
case _ => JsError(s"Either ${JsPath() \ VALUE_KEY} must be provided, or ${JsPath() \ IS_INFINITE_KEY} must be provided as true")
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment