使用Circe自定义编解码器将json解码为案例类列表

时间:2019-07-03 21:18:56

标签: json scala decode circe

我正在尝试使用Circe的自定义编解码器将json解码为特征列表Feature,该特征列表分为两种情况:

trait Feature {
  def name: String
  def index: Int
  def frequency: Int
}

case class NumericFeature(name, index, frequency) extends Feature
case class SetFeature(name, index, set, frequency) extends Feature

来自此处显示的json:

[
 {
   "name" : "ElectionReturns_G16CountyTurnoutAllRegisteredVoters",
   "index" : 1770,
   "frequency" : 2992
 },
{
   "name" : "CommercialDataLL_Home_Owner_Or_Renter",
   "index" : 1112,
   "set" : [
     "Likely Homeowner",
     "",
     "Likely Renter",
    ],
   "frequency" : 2537
},
   .
   .
   .
   .
]

这是适用于案例类又名单个实例的代码:

{
   "name" : "ElectionReturns_G16CountyTurnoutAllRegisteredVoters",
   "index" : 1770,
   "frequency" : 2992
 }
import io.circe.Json
import io.circe._
import io.circe.parser._

implicit val decoder: Decoder[Feature] = new Decoder[Feature] {
      final def apply(h: HCursor): Decoder.Result[Feature] = for {

          name <- h.get[String]("name")
          index <- h.get[Int]("index")
          set <- h.getOrElse[Set[String]]("set")(Set[String]())
          frequency <- h.get[Int]("frequency")
          feature: Feature = set match {
            case s if s.isEmpty => new NumericFeature(name, index, frequency)
            case _ => new SetFeature(name, index, set, frequency)
          }
        } yield feature
     }

val decoded = decoder.decodeJson(parse(json).getOrElse(Json.Null))

如何调整它以输出列表?我曾尝试仅将解码器的输出类型更改为List[Feature],因为我认为for循环会生成一个列表,但事实并非如此。

这是我尝试在解码器中返回Decoder [List [Feature]]:

implicit val decoder: Decoder[List[Feature]] = new Decoder[List[Feature]] {
      final def apply(h: HCursor): Decoder.Result[List[Feature]]= {

        val feature = for {

          name <- h.get[String]("name")
          index <- h.get[Int]("index")
          set <- h.getOrElse[Set[String]]("set")(Set[String]())
          frequency <- h.get[Int]("frequency")
          feature: Feature = set match {
            case s if s.isEmpty => new NumericFeature(name, index, frequency)
            case _ => new SetFeature(name, index, set, frequency)
          }
        } yield feature
        feature.asInstanceOf[Decoder.Result[List[Feature]]]
      }
    }
val decoded = decoder.decodeJson(parse(json).getOrElse(Json.Null))

2 个答案:

答案 0 :(得分:0)

只要您在范围内拥有io.circe.parser.decode,就使用Decoder[Feature]

io.circe.parser.decode[Seq[Feature]](json)

您不必提供Decoder[Seq[Feature]]

答案 1 :(得分:-1)

尝试使用自定义解码器。这种方法对我有用:

import cats.Show
import cats.implicits._
import io.circe.Decoder

object Feature {
  implicit val featureDecoder: Decoder[Feature] = List[Decoder[Feature]](
    Decoder[NumericFeature].widen,
    Decoder[SetFeature].widen
  ).reduceLeft(_ or _)
}