Last active
June 27, 2017 15:18
-
-
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 file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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