mogli
mogli

Reputation: 1609

serialize Map with key and value as case class using circe

Below is the simplified code that has a Map with key and value as case class. Key and value object are successfully serialized with circe. But facing challenge to serialize Map[CaseClassKey, CaseClassValue] with circe.

//////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 link : https://scalafiddle.io/sf/SkZNa1L/2

Note : Looking to just serialize and deserialize data (Map[Person, Basket]) correctly. How json looks is not really important in this particular case.

Upvotes: 0

Views: 660

Answers (1)

tentacle
tentacle

Reputation: 553

Strictly speaking, you are trying to create an invalid json. Json map structure isn't an arbitrary map, it's an object structure where keys are property names. https://www.json.org/json-en.html

See also Can we make object as key in map when using JSON?

Update:

I suggest a slight change to your model to get the job done. Instead of Map use array of objects, each having two properties: key and value

Something like this:

case class Entry(key: Person, value: Basket)

So you can replace Map[Person, Basket] with Seq[Entry], and convert it back to Map if needed.

Upvotes: 3

Related Questions