Skip to content

Instantly share code, notes, and snippets.

@phdoerfler
Created April 12, 2021 19:40
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save phdoerfler/268184de4d63f91e9115bf7e189f4008 to your computer and use it in GitHub Desktop.
Save phdoerfler/268184de4d63f91e9115bf7e189f4008 to your computer and use it in GitHub Desktop.
fancy circe sttp failures
package io.doerfler
import sttp.client3._
import sttp.client3.circe._
import io.circe._
// For fancy debugging
import io.circe._, io.circe.generic.auto._, io.circe.parser._, io.circe.syntax._
import better.files._
import File._
import java.io.{File => JFile}
object VerboseDecodingFailures extends VerboseDecodingFailures
trait VerboseDecodingFailures {
def asJsonUnsafeVerbose[B: Decoder: IsOption]: ResponseAs[B, Any] =
asStringAlways.map(deserializeOrThrowVerbose(deserializeJson))
def deserializeOrThrowVerbose[E, T](doDeserialize: String => Either[io.circe.Error, T]): String => T = s =>
doDeserialize(s) match {
case Left(df: DecodingFailure) =>
val show = implicitly[cats.Show[DecodingFailure]]
val msg = parse(s).toOption.map { js =>
var lastGood = js.hcursor.replayOne(df.history.head)
System.err.println(js.hcursor.replay(df.history).focus.map(_.spaces2))
val tmp = File.newTemporaryFile("", ".json")
tmp.write(tryFocus(js, df.history).spaces2SortKeys)
s"${show.show(df)}${System.lineSeparator}The offending JSON has been saved to ${tmp.uri}"
}.getOrElse(show.show(df))
throw df.copy(message = msg)
case Left(e) => throw DeserializationException(s, e)
case Right(b) => b
}
def tryFocus(js: Json, hist: List[CursorOp]): Json = hist match {
case Nil => js
case head :: tail => js.hcursor.replayOne(head).focus match {
case Some(value) => tryFocus(value, tail)
case None => js
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment