sttp.client4.upicklejson.SttpUpickleApi.scala Maven / Gradle / Ivy
The newest version!
package sttp.client4.upicklejson
import sttp.client4._
import sttp.client4.internal.Utf8
import sttp.model.MediaType
import sttp.client4.json._
trait SttpUpickleApi {
val upickleApi: upickle.Api
implicit def upickleBodySerializer[B](implicit encoder: upickleApi.Writer[B]): BodySerializer[B] =
b => StringBody(upickleApi.write(b), Utf8, MediaType.ApplicationJson)
/** If the response is successful (2xx), tries to deserialize the body from a string into JSON. Returns:
* - `Right(b)` if the parsing was successful
* - `Left(HttpError(String))` if the response code was other than 2xx (deserialization is not attempted)
* - `Left(DeserializationException)` if there's an error during deserialization
*/
def asJson[B: upickleApi.Reader: IsOption]: ResponseAs[Either[ResponseException[String, Exception], B]] =
asString.mapWithMetadata(ResponseAs.deserializeRightWithError(deserializeJson)).showAsJson
/** Tries to deserialize the body from a string into JSON, regardless of the response code. Returns:
* - `Right(b)` if the parsing was successful
* - `Left(DeserializationException)` if there's an error during deserialization
*/
def asJsonAlways[B: upickleApi.Reader: IsOption]: ResponseAs[Either[DeserializationException[Exception], B]] =
asStringAlways.map(ResponseAs.deserializeWithError(deserializeJson)).showAsJsonAlways
/** Tries to deserialize the body from a string into JSON, using different deserializers depending on the status code.
* Returns:
* - `Right(B)` if the response was 2xx and parsing was successful
* - `Left(HttpError(E))` if the response was other than 2xx and parsing was successful
* - `Left(DeserializationException)` if there's an error during deserialization
*/
def asJsonEither[E: upickleApi.Reader: IsOption, B: upickleApi.Reader: IsOption]
: ResponseAs[Either[ResponseException[E, Exception], B]] =
asJson[B].mapLeft {
case HttpError(e, code) => deserializeJson[E].apply(e).fold(DeserializationException(e, _), HttpError(_, code))
case de @ DeserializationException(_, _) => de
}.showAsJsonEither
def deserializeJson[B: upickleApi.Reader: IsOption]: String => Either[Exception, B] = { (s: String) =>
try
Right(upickleApi.read[B](JsonInput.sanitize[B].apply(s)))
catch {
case e: Exception => Left(e)
case t: Throwable =>
// in ScalaJS, ArrayIndexOutOfBoundsException exceptions are wrapped in org.scalajs.linker.runtime.UndefinedBehaviorError
t.getCause match {
case e: ArrayIndexOutOfBoundsException => Left(e)
case _ => throw t
}
}
}
}