Как определить импликации для Map двух классов? - PullRequest
0 голосов
/ 11 февраля 2020
case class Apple(id:String, name:String)
case class Fruit(id:String,ftype:String)

case class Basket(b:Map[Fruit,Apple])

Как определить игровые последствия, так как приведенного ниже определения недостаточно.

 implicit val format: Format[Fruit] = Json.format
 implicit val format: Format[Apple] = Json.format

Это не работает:

 implicit val format: Format[Basket] = Json.format

Ответы [ 2 ]

2 голосов
/ 11 февраля 2020

Форматировщик в порядке, но он работает только для Классы дел .

Так что все, что вам нужно сделать, это настроить их:

case class Apple(id:String, name:String)
case class Fruit(id:String,ftype:String)

case class Basket(b:Map[Fruit,Apple])

Обновление

Хорошо, есть другая проблема. JSON имеет ограничение, согласно которому ключ карты должен быть строкой .

Смотрите мой ответ здесь: { ссылка }

Хорошо, вот пример для Play <2.8 </strong>:

  implicit val formata: Format[Apple] = Json.format

  implicit val mapReads: Reads[Map[Fruit, Apple]] = (jv: JsValue) =>
    JsSuccess(jv.as[Map[String, Apple]].map { case (k, v) =>
      (k.split("::").toList match {
        case id :: ftype :: _ => Fruit(id, ftype)
        case other => throw new IllegalArgumentException(s"Unexpected Fruit Key $other")
      }) -> v
    })

  implicit val mapWrites: Writes[Map[Fruit, Apple]] = (map: Map[Fruit, Apple]) =>
    Json.toJson(map.map { case (fruit, o) =>
      s"${fruit.id}::${fruit.ftype}" -> o
    })
  implicit val jsonMapFormat: Format[Map[Fruit, Apple]] = Format(mapReads, mapWrites)

  implicit val formatb: Format[Basket] = Json.format

С этим примером данных он работает:

  val basket = Basket(Map(Fruit("12A", "granate") -> Apple("A11", "The Super Apple"),
     Fruit("22A", "gala") -> Apple("A21", "The Gala Premium Apple")))
  val json = Json.toJson(basket) // >> {"b":{"12A::granate":{"id":"A11","name":"The Super Apple"},"22A::gala":{"id":"A21","name":"The Gala Premium Apple"}}}
  json.as[Basket] // >> Basket(Map(Fruit(12A,granate) -> Apple(A11,The Super Apple), Fruit(22A,gala) -> Apple(A21,The Gala Premium Apple)))

Здесь Scalafiddle

1 голос
/ 12 февраля 2020

Вот возможная реализация с использованием Play JSON 2.8:

import play.api.libs.json._

case class Apple(id:String, name:String)
case class Fruit(id:String,ftype:String)

case class Basket(b:Map[Fruit,Apple])

object Apple {
  implicit val format = Json.format[Apple]
}

object Basket {
  implicit val keyReads: KeyReads[Fruit] = s => ???
  implicit val keyWrites: KeyWrites[Fruit] = f => s"${f.id}/${f.ftype}"

  implicit val format = Json.format[Basket]
}

val b = Basket(Map(Fruit("1", "sw") -> Apple("2", "boskop")))

Json.stringify(Json.toJson(b)) // -> {"b":{"1/sw":{"id":"2","name":"boskop"}}}

https://scastie.scala-lang.org/XbFY6amKSb6BCVCrGmgrBQ

...