Есть сложный json объект. Поле «значение» в декодировании может иметь разные типы. Я новичок в scala, поэтому я буду благодарен за любую идею, чтобы сделать это.
{"price":0,
"price_currency":"USD",
"decode":[
{"label":"Make","value":"BMW"},
{"label":"Model Year","value":2017},
{"label": "Equipment", "value": [ "Liftgate", "Packages"] }
{"label": "Price", "value": [
{"date": "2015-06-10", "price": 20500,"currency": "EUR"},
{ "date": "2015-09-21", "price": 20000,"currency": "EUR"}
]}
]}
поле «значение» имеет различные типы: Double, String, Seq [String], объект, который я пытался создать общую черту для этих типов и пользовательский декодер, но оказалось,
ОБНОВЛЕНИЕ привет, я хочу поделиться решением для такой структуры, можно было сделать неявное
case class VinInfo (price: Double,
price_currency: String,
decode: Seq[VinDecodeDetails])
sealed trait VinDecodeDetails
case class VinDecodeString(label: String, value: String) extends VinDecodeDetails
case class VinDecodeEquipment(label: String, value: Seq[String]) extends VinDecodeDetails
case class VinDecodePrice(label: String, value: Seq[VinPrice]) extends VinDecodeDetails
case class VinPrice(date: String, price: Double, currency: String)
object VinDecodeDetails
implicit val eitherDoubleOrString: Decoder[Either[Double, String]] =
Decoder[Double].map(Left(_)).or(Decoder[String].map(Right(_)))
implicit val decodeVinInfo: Decoder[VinInfo] = new Decoder[VinInfo] {
final def apply(c: HCursor): Decoder.Result[VinInfo] =
for {
price <- c.downField("price").as[Double]
price_currency <- c.downField("price_currency").as[String]
decode <- c.downField("decode").as[Seq[VinDecodeDetails]]
} yield {
new VinInfo(price, price_currency, decode)
}
}
implicit val decodeVinDecodeDetails: Decoder[VinDecodeDetails] = new Decoder[VinDecodeDetails] {
final def apply(c: HCursor): Decoder.Result[VinDecodeDetails] =
for {
decodeLabel <- c.downField("label").as[String]
value = c.downField("value")
vinDecodeDetails <- decodeLabel match {
case "Equipment" => value.as[Seq[String]]
case "Price" => value.as[Seq[VinPrice]]
case _ => value.as[Either[Double, String]].map{
case Right(s) => s.toString
case Left(d) => d.toString
}
}
} yield {
decodeLabel match {
case "Equipment" => VinDecodeEquipment("Equipment", vinDecodeDetails.asInstanceOf[Seq[String]])
case "Price" => VinDecodePrice("Price", vinDecodeDetails.asInstanceOf[Seq[VinPrice]])
case _ => VinDecodeString(decodeLabel, vinDecodeDetails.asInstanceOf[String])
}
}
}