bizzabo / play-json-extensions

+22 field case class formatter and more for play-json
http://cvogt.org/play-json-extensions/api/
Other
196 stars 44 forks source link

generalize tagging serialized data with type, etc #18

Open cvogt opened 8 years ago

cvogt commented 8 years ago

generalize:

  implicit class FormatTagExtension[T](enclosed: Format[T]){
​
    def tagWithType(implicit classTag: ClassTag[T]): Format[T] = new Format[T]{
​
      def reads(jsValue: JsValue): JsResult[T] = {
​
        val className = classTag.runtimeClass.getSimpleName
​
        jsValue\"type" match {
          case x: JsDefined => x.value.validate[String].filter(_ == className).flatMap(_ => enclosed.reads(jsValue))
          case other => JsError(s"tagWithType cannot deserialize json without a matching type field. Found: " + jsValue)
        }
​
      }
​
      def writes(value: T): JsValue = {
​
        val className = classTag.runtimeClass.getSimpleName
​
        enclosed.writes(value) match{
          case x: JsObject => x ++ JsObject(Map("type" -> JsString(className)))
          case other => throw new Exception(s"Cannot use tagWithType on Format[$className], because writes didn't return a JsObject but: " + other + " for " + value)
        }
​
      }

    }
​
  }
graingert commented 7 years ago

@alkersan @cvogt this is like Variant types from https://github.com/aparo/play-json-extra