score:3

Accepted answer

Have a look at ScalaJsonTransformers. You can create a transformer that creates the normalised field from a string data value and use it to, erm, transform your original Format to a new Writes. Here's a slightly simplified example that could doubtless be improved (you'll want to check various edge cases):

case class ChecklistColumn(kind: String, descriptor: String, data: JsValue)

// The original format.
val checklistFormat: Format[ChecklistColumn] = (
  (__ \ "kind").format[String] and
  (__ \ "descriptor").format[String] and
  (__ \ "data").format[JsValue]
)(ChecklistColumn.apply, unlift(ChecklistColumn.unapply))

// A transformer that looks for a "data" field with a string
// value and adds the normalized_data field if it finds one.
val checklistTransformer: Reads[JsObject] = JsPath.json.update(
  (__ \ "data").read[String].flatMap (
     str => (__ \ "normalized_data").json.put(JsString(str + "!!!"))))

// A new derived Writes which writes the transformed value if
// the transformer succeeds (a data string), otherwise the
// original value.
implicit val checklistWrites: Writes[ChecklistColumn] = checklistFormat
  .transform (js => js.transform(checklistTransformer).getOrElse(js))

That gives me:

Json.prettyPrint(Json.toJson(ChecklistColumn("a", "b", JsNumber(1))))
// {
//   "kind" : "a",
//   "descriptor" : "b",
//   "data" : 1
// }

Json.prettyPrint(Json.toJson(ChecklistColumn("a", "b", JsString("c"))))
// {
//   "kind" : "a",
//   "descriptor" : "b",
//   "data" : "c",
//   "normalized_data" : "c!!!"
// }

Related Query

More Query from same tag