问题描述
下面是一个简化的代码,它有一个带有键和值的 Map 作为案例类。 使用 circe 成功序列化键和值对象。 但是面临用circe序列化Map[CaseClassKey,CaseClassValue]的挑战。
//////case classes and common vals starts here//////
case class Person(personId : Int,phoneNumber : Int)
case class Item(name : String)
case class Basket(items : List[Item],bills : Map[Int,Int])
def createBasketInstance() : Basket = {
val milk = Item("milk")
val coffee = Item("coffee")
val bills = Map(1 -> 20,2 -> 75)
Basket( List(milk,coffee),bills )
}
val basket = createBasketInstance()
val person = Person(1,987654)
//////case classes and common vals ends here//////
import io.circe._
import io.circe.generic.semiauto._
import io.circe.syntax._
import io.circe.parser._
//Serializing Person instance that is used as Key in Map
{
implicit val personCodec :Codec[Person] = deriveCodec[Person]
val jsonString = person.asJson.spaces2
println(jsonString)
}
println("-" * 50)
//Serializing Basket instance that is used as Value in Map
{
implicit val itemCodec :Codec[Item] = deriveCodec[Item]
implicit val basketCodec :Codec[Basket] = deriveCodec[Basket]
val jsonString = basket.asJson.spaces2
println(jsonString)
}
println("-" * 50)
//Serializing Map[Person,Basket]
//TODO : not able to make it work
{
implicit val itemCodec :Codec[Item] = deriveCodec[Item]
implicit val basketCodec :Codec[Basket] = deriveCodec[Basket]
val map = Map(person -> basket)
//TODO : How to make below lines work
//val jsonString = map.asJson.spaces2
//println(jsonString)
}
scalafiddle 链接:https://scalafiddle.io/sf/SkZNa1L/2
注意:希望正确地序列化和反序列化数据 (Map[Person,Basket])。在这种特殊情况下,json 的外观并不重要。
解决方法
严格来说,您正在尝试创建无效的 json。 Json 映射结构不是任意映射,它是一个对象结构,其中键是属性名称。 https://www.json.org/json-en.html
另见Can we make object as key in map when using JSON?
更新:
我建议对您的模型稍作更改以完成工作。 代替 Map 使用对象数组,每个对象都有两个属性:键和值
像这样:
case class Entry(key: Person,value: Basket)
因此您可以将 Map[Person,Basket] 替换为 Seq[Entry],并在需要时将其转换回 Map。