Search code examples
jsonscalaimplicit-conversionargonaut

In Scala, how to apply implicit conversion to subtypes of a collection?


I am trying to convert a list of objects to json using argonaut. The list contains a list of validation errors of varying type. For example it can contain an instance of 'MissingParameter' or, 'InvalidParameter' or any other type. I have defined EncodeJson (argonaut) codecs for both classes mentioned above. Is there any way I can convert a list of the above types to json using argonaut? I mean, can I achieve the following?

List(new MissingParameter("name"), new InvalidParameter("email")).asJson

Solution

  • I haven't used argonaut, but I guess the problem here is a general issue. The type of the list here is List[Product with Serializable]. And the compiler won't know how to serialize it to Json.

    I would suggest you to create a Parameter trait, extend the classes with it, and write a serializer for Parameter that checks all the types with pattern matching:

    Note: I'm using play-json library, you should adapt it to argonaut.

    import play.api.libs.json.{Writes, JsValue, Json}
    import play.api.libs.json.Writes._
    
    trait Parameter
    
    case class MissingParameter (paramName: String) extends Parameter
    
    case class InvalidParameter (paramName: String) extends Parameter
    
    implicit val writes1 = Json.writes[MissingParameter]
    implicit val writes2 = Json.writes[InvalidParameter]
    
    implicit val implicitParamWrites = new Writes[Parameter] {
      def writes(param: Parameter): JsValue = {
        param match {
          case missing: MissingParameter => Json.toJson(missing)
          case invalid: InvalidParameter => Json.toJson(invalid)
        }
      }
    }
    
    val list: List[Parameter] = List( MissingParameter("p1"), InvalidParameter("i1") )
    
    Json.toJson(list)