Search code examples
jsonscalacirce

Scala Circe. Encoder type Any


I am trying encode class ResponseResult to json

case class ResponseResult (var Code : Int,
                 var Message: String,
                 var Data: Any )

var json = ResponseResult(1, "2", List(3,4,5)).asJson

I get an error could not find implicit value for parameter encoder: io.circe.Encoder[ResponseResult]

Then I create encoder

object ResponseResult {
    implicit val encodeResult: Encoder[ResponseResult] =
        Encoder.forProduct3[ResponseResult, Int, String, Any]("Code", "Message", "Data") {
            case ResponseResult(c, m, d) => (c, m, d.toString)
        }
}

I get an error could not find implicit value for parameter encoder: Encoder[Any]

This is my full code

import io.circe.Encoder
import io.circe.generic.auto._
import io.circe.syntax._

object a {
  case class ResponseResult (var Code : Int,
                             var Message: String,
                             var Data: Any )
  object ResponseResult {
    implicit val encodeResult: Encoder[ResponseResult] =
      Encoder .forProduct3[ResponseResult, Int, String, Any]("Code", "Message", "Data") {
        case ResponseResult(c, m, d) => (c, m, d.toString)
      }
  }

  def main(args: Array[String]): Unit = {
    var json = ResponseResult(1, "2", List(3,4,5)).asJson
  }
}

Anyone can show me How to encode class ResponseResult. Thank you


Solution

  • Well, you cannot have Codec for Any type, simple as that.

    If you want to pass some value there, serialize it and be able to deserialize it later, you have to assume some type. You can defer this assumption by using type parameter:

    case class ResponseResult[Data](Code : Int,
                                    Message: String,
                                    Data: Data)
    

    and requiring existence of encoder for this type parameter:

    object ResponseResult {
      implicit def encodeResult[Data: Encoder]: Encoder[ResponseResult[Data]] =
        Encoder.forProduct3[ResponseResult[Data], Int, String, Data]("Code", "Message", "Data") {
          case ResponseResult(c, m, d) => (c, m, d)
        }
    }
    

    then you will be able to serialize data like you want

    // inferred to ResponseResult[List[Int]]
    val response = ResponseResult(1, "2", List(3,4,5))
    
    // and Circe can generate codec for List[Int] automatically
    // so it can now generate codec for ResponseResult[List[Int]]
    val json = response.asJson