Использование пользовательского кодека Circe для декодирования json в список класса case - PullRequest
2 голосов
/ 04 июля 2019

Я пытаюсь использовать пользовательские кодеки Circe для декодирования json в Список признаков Feature, который разбит на два класса case:

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 выдаст список, но это не так.

Вот моя попытка декодера вернуть декодер[Список [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))

1 Ответ

0 голосов
/ 04 июля 2019

Просто используйте io.circe.parser.decode, если у вас есть Decoder[Feature] в области действия:

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

Вам не нужно предоставлять Decoder[Seq[Feature]].

...