I am trying to use Circe's custom codecs to decode json to a List of a trait Feature
which is broken down into two case classes:
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
from the json shown here:
[
{
"name" : "ElectionReturns_G16CountyTurnoutAllRegisteredVoters",
"index" : 1770,
"frequency" : 2992
},
{
"name" : "CommercialDataLL_Home_Owner_Or_Renter",
"index" : 1112,
"set" : [
"Likely Homeowner",
"",
"Likely Renter",
],
"frequency" : 2537
},
.
.
.
.
]
This is the code that works for a single instance of a case class aka:
{
"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))
How can I adapt this to output a list? I have tried just changing the output type of the decoder to List[Feature]
because I thought the for loop would yield a list, but this isn't the case.
Here is my attempt at a Decoder returning a 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))