title: How do I override default codec in circe?
body: <p>I'd like to encode <code>Array[Byte]</code> fields of my case classes as Base64 strings. For some reason Circe doesn't pick up my codec using default one instead that converts byte array into json array of ints.</p>
  
  <p>What should I do to fix it ? Here is my minimized code</p>
  
  <pre><code>import io.circe.generic.JsonCodec
  
  sealed trait DocumentAttribute
  
  @JsonCodec
  sealed case class DAAudio(title: Option[String], performer: Option[String], waveform: Option[Array[Byte]], duration: Int) extends DocumentAttribute
  
  @JsonCodec
  sealed case class DAFilename(fileName: String) extends DocumentAttribute
  
  object CirceEncodersDecoders {
    import io.circe._
    import io.circe.generic.extras._
    import io.circe.generic.extras.semiauto._
  
    implicit val arrayByteEncoder: Encoder[Array[Byte]] = Encoder.encodeString.contramap[Array[Byte]] { bytes ⇒
      Base64.getEncoder.encodeToString(bytes)
    }
  
    val printer: Printer = Printer.noSpaces.copy(dropNullValues = true, reuseWriters = true)
    implicit val config: Configuration = Configuration.default.withDiscriminator("kind").withSnakeCaseConstructorNames.withSnakeCaseMemberNames
  
    implicit val DocumentAttributeEncoder: Encoder[DocumentAttribute] = deriveEncoder
    implicit val DocumentAttributeDecoder: Decoder[DocumentAttribute] = deriveDecoder
  }
  
  object main {
    def main(args: Array[String]): Unit = {
      import CirceEncodersDecoders._
  
      import io.circe.parser._
      import io.circe.syntax._
  
      val attributes: List[DocumentAttribute] = List(
        DAAudio(Some("title"), Some("perform"), Some(List(1, 2, 3, 4, 5).map(_.toByte).toArray), 15),
        DAFilename("filename")
      )
      val j2 = attributes.asJson
      val decoded2 = decode[List[DocumentAttribute]](j2.noSpaces)
      println(decoded2)
    }
  }
  </code></pre>