Je construisons le back-end d'une application à l'aide de http4s. Dans l'application, je reçois une réponse JSON d'une API externe (pas celle que je travaille). La réponse de l'API est de ce modèle ci-dessous.
JSON Réponse: P>
object Stocks { case class tickerInfo(ticker: String, dim:String, date: String, a: Int, b: Int, c: Float, d: Int, e: Int) case class data(data: Seq[tickerInfo]) case class meta(next_date : Option[String]) case class table(data: data, meta:meta) case class stockInfo(datatable:table) object stockInfo { implicit def stockInfoEntityDecoder[F[_]:Sync]: EntityDecoder [F, stockInfo] = jsonOf implicit def stockInfoEntityEncoder[F[_] : Applicative]: EntityEncoder[F, stockInfo] = jsonEncoderOf } val decodedJson = C.expect[stockInfo](GET(Uri.uri("www.externalApi.com") }
3 Réponses :
Vous devez: P>
Si vous avez tout fait correctement, vous devriez alors pouvoir utiliser client http4s Pour récupérer les données, e. g. httpclient.Expective [YourModelClass] (Uri.uri ("http://somewhere.com/something/")) code>. P>
Bienvenue! Je commencerais probablement à l'intérieur et de passer votre chemin hors:
Ainsi, pour les éléments du tableau Code> Data Code>, peut-être quelque chose comme (je devine sur le domaine): P>
elem match { case name :: mart :: date :: a :: b :: price :: c :: d :: Nil => Stock(name, mart, date, a, b, price, c, d) case invalid @ _ => log.warn(s"Invalid record: $invalid") }
J'ai mis à jour la question à montrer où je suis toujours bloqué. S'il vous plait aidez si vous le pouvez
Je suis courant dans une erreur invalideMessageBody. Pouvez-vous aider avec ça?
Vous avez quelques erreurs dans votre modèle, mais le problème principal est que
Si vous ne pouvez pas modifier la source des données, vous devez créer votre propre codec personnalisé. object Stocks {
final case class TickerInfo(ticker: String, dim: String, date: String, a: Int, b: Int, c: Float, d: Int, e: Int)
final case class Meta(next_date : Option[String])
final case class Table(data: List[TickerInfo], meta: Meta)
final case class StockInfo(datatable: Table)
object StockInfo {
implicit final val TickerInfoDecoder: Decoder[TickerInfo] = Decoder[List[Json]].emap {
case ticker :: dim :: date :: a :: b :: c :: d :: e :: Nil =>
(
ticker.as[String],
dim.as[String],
date.as[String],
a.as[Int],
b.as[Int],
c.as[Float],
d.as[Int],
e.as[Int]
).mapN(TickerInfo).left.map(_.toString)
case list =>
Left(s"Bad number of fields in: ${list.mkString("[", ", ", "]")}")
}
implicit final val MetaDecoder: Decoder[Meta] = deriveDecoder
implicit final val TableDecoder: Decoder[Table] = deriveDecoder
implicit final val StockInfoDecoder: Decoder[StockInfo] = deriveDecoder
}
}
@ Luismiguelmejíasuárez, désolé pour ça. Je voulais dire décodeur d'entité et codeur d'entité pour http4s. J'ai besoin de créer un objet qui a une entité implicite du décodeur et de l'entité codeur pour décoder le JSON que je reçois ci-dessus. Le format du JSON est ce que j'ai créé ci-dessus. J'espère que cela est plus clair maintenant? Merci
@ Luismiguelmejíasuárez J'ai essayé de créer un objet qui contiendrait le JSON décodé. Semblable à la réponse fournie ci-dessous, mais sa réponse n'est pas complète, comme vous l'avez dit.
@ Luismiguelmejíasuárez J'ai mis à jour la question maintenant. Merci
@ Luismiguelmejíasuárez Ses échoue avec une erreur http4s - InvalidMessageBodyFailure. J'ai eu cette erreur dans le passé et c'était lorsque le décodeur d'entité ne pouvait pas décoder le JSON entrant.