-2
votes

Décode d'entité pour JSON qui renvoie une liste / SEQ de n'importe quel Val

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")
     }


4 commentaires

@ 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.


3 Réponses :


0
votes

Vous devez:

  1. Créez un modèle de données, consistant probablement en certaines classes de cas et des traits éventuellement scellés. Ce que ce modèle de données devrait ressembler dépend de l'API externe que vous parlez.
  2. Créez des décodeurs JSON pour ce modèle de données. Ceux-ci devraient aller dans les objets de compagnon de classes de cas, car cela permettra au compilateur de les trouver en cas de besoin sans avoir à importer quoi que ce soit.
  3. Utilisez la bibliothèque HTTP4S-CIRCE afin d'intégrer ces décodeurs avec http4s. https://http4s.org/v0.19/json/

    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/")) .


0 commentaires

0
votes

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")
}


2 commentaires

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?



1
votes

Vous avez quelques erreurs dans votre modèle, mais le problème principal est que Circe STRY> ne sera pas en mesure de décoder automatiquement un tableau de Jsons dans une classe de cas.
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
  }
}


0 commentaires