These are chat archives for argonaut-io/argonaut

17th
Jul 2017
Mark
@Fristi
Jul 17 2017 15:03
Is there a variant of xmap on CodecJson where decoding of failure is taken in to account ?
Mark
@Fristi
Jul 17 2017 15:44
This is not nice to write
implicit val json: CodecJson[MerchantStatus] = codecJson[String]
    .xmap[MerchantStatus](x => fromString(x).getOrElse(sys.error(s"Could not map '$x' to a MerchantStatus")))(_.status)
Colt Frederickson
@coltfred
Jul 17 2017 15:49
@Fristi The best thing to do is to write an encode json and decode json instance separately which correctly addresses the partiality of your conversion.
Mark
@Fristi
Jul 17 2017 16:31

This might be a useful contribution:

  implicit class RichCodecJson[A](val codecJson: CodecJson[A]) {
    def narrow[B](f: B => A, g: A => String \/ B): CodecJson[B] =
      CodecJson(
        x => codecJson.encode(f(x)),
        cur =>
          codecJson.decode(cur).flatMap(x => g(x).fold(err => DecodeResult.fail(err, cur.history), DecodeResult.ok))
      )
  }

Resulting:

codecJson[String]
    .narrow[MerchantStatus](
      _.status,
      x => fromString(x).fold[String \/ MerchantStatus](-\/(s"Could not map '$x' to MerchantStatus"))(\/-.apply)
    )