简体   繁体   中英

circe encoding putting :: when a list of case class from trait is not sealed

Hello everyone I am facing a problem with the circe library to translate between json and at scala case class any help will be highly appreciate.

in the past i have an ADT like this.

sealed trait Sons

case class Son1(name: String, belongings: List[String]) extends Sons
case class Son2(lastName: String, belongings: List[String]) extends Sons

and have no problems whatsoever but now because of the design the file in witch this trait is, is costly to change we have to remove the sealed from the trait so now we have this (with the sons in different files/libraries)

trait Sons

case class Son1(name: String, belongings: List[String]) extends Sons
case class Son2(lastName: String, belongings: List[String]) extends Sons

when trying to convert a list of sons from Scala to json the library puts:: before the list generating a problem as can be seen in this example.

object Test extends App{


implicit val encoderSon1: Encoder[Son1]=deriveEncoder[Son1]
  implicit val decoderSon1: Decoder[Son1]=deriveDecoder[Son1]
  implicit val encoderSon2: Encoder[Son2]=deriveEncoder[Son2]
  implicit val decoderSon2: Decoder[Son2]=deriveDecoder[Son2]

  implicit val encoderSon: Encoder[Sons] = Encoder.instance {
    case son1: Son1 => son1.asJson
    case son2: Son2 => son2.asJson
  }

  implicit val DecoderSon: Decoder[Sons] =
    List[Decoder[Sons]](
      Decoder[Son1].widen,
      Decoder[Son2].widen
    ).reduceLeft(_ or _)

  implicit val encoderSonList: Encoder[List[Sons]] = deriveEncoder
  implicit val DecoderSonList: Decoder[List[Sons]] = deriveDecoder

  val sonsList: List[Sons] = List(Son1("James",List()),Son2("Mike",List()))
  println(s"1->${sonsList}")
  println(s"2->${sonsList.asJson.noSpaces}")
  val andBack=decode[List[Sons]](sonsList.asJson.noSpaces).fold(fa=>fa.getMessage,fb=>fb.toString())
  println(s"3->${andBack}")
}

the prints are printint

1->List(Son1(James,List()), Son2(Mike,List()))
2->{"::":[{"name":"James","belongings":[]},{"lastName":"Mike","belongings":[]}]}
3->Attempt to decode value on failed cursor: DownField(head),DownField(::)

the problem is of course i do not want the list to be put in a field called:: when converting to JSON.

thank you for any help possible:D

Don't use semi auto for List - semiauto uses slightly different mechanism than other derivations to eg avoid issues like:

implicit val x: X = implicitly[X] // uses val x, so we have cyclic dependency = error in runtime

For that reason when you are using semiauto here, List instances from Encoder and Decoder are ignored, and instead macro generates code for List ADT - that is case class:: and case object Nil .

If you remove


  implicit val encoderSonList: Encoder[List[Sons]] = deriveEncoder
  implicit val DecoderSonList: Decoder[List[Sons]] = deriveDecoder

it will work again.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM