Skip to content

Instantly share code, notes, and snippets.

@agemooij
Last active November 28, 2022 13:50
Show Gist options
  • Save agemooij/f2e4075a193d166355f8 to your computer and use it in GitHub Desktop.
Save agemooij/f2e4075a193d166355f8 to your computer and use it in GitHub Desktop.
More advanced example of a custom spray-json format
implicit object ProductItemFormat extends RootJsonFormat[ProductItem] {
// some fields are optional so we produce a list of options and
// then flatten it to only write the fields that were Some(..)
def write(item: ProductItem) = JsObject(
List(
Some("product_number" -> item.productNumber.toJson),
item.ean.map(ean ⇒ "ean" -> ean.toJson),
Some("title" -> item.title.toJson),
item.description.map(description ⇒ "description" -> description.toJson),
Some("price" -> item.price.toJson),
Some("original_price" -> item.originalPrice.toJson),
item.scratchPrice.map(scratchPrice ⇒ "scratch_price" -> scratchPrice.toJson),
Some("scratch_price_to_display" -> item.scratchPriceToDisplay.toJson), // calculated field used by the UI
Some("size" -> item.size.toJson),
Some("availableStock" -> item.availableStock.toJson),
Some("shipping" -> item.shipping.toJson),
Some("vat_code" -> item.vatCode.toJson),
Some("vat_percentage" -> item.vatPercentage.toJson)
).flatten: _*
)
// we use the "standard" getFields method to extract the mandatory fields.
// For optional fields we extract them directly from the fields map using get,
// which already handles the option wrapping for us so all we have to do is map the option
def read(json: JsValue) = {
val jsObject = json.asJsObject
jsObject.getFields("product_number", "title", "price", "original_price", "size", "availableStock", "shipping", "vat_code", "vat_percentage") match {
case Seq(number, title, price, originalPrice, size, availableStock, shipping, vatCode, vatPercentage) ⇒ ProductItem(
number.convertTo[String],
jsObject.fields.get("ean").map(_.convertTo[String]),
title.convertTo[String],
jsObject.fields.get("description").map(_.convertTo[String]),
price.convertTo[Int],
originalPrice.convertTo[Int],
jsObject.fields.get("scratch_price").map(_.convertTo[Int]),
size.convertTo[Size], // notice that this just works (TM) as long as the required json format is implicitly available
availableStock.convertTo[Int],
shipping.convertTo[ShippingInfo], // notice that this just works (TM) as long as the required json format is implicitly available
vatCode.convertTo[String],
vatPercentage.convertTo[Int]
)
case other ⇒ deserializationError("Cannot deserialize ProductItem: invalid input. Raw input: " + other)
}
}
}
@SivaKaviyappa
Copy link

Can you please give the sample json that goes with this? It will help us in understanding . Thanks .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment