简体   繁体   中英

Use a custom type parameter to auto map a JSON response

Can I pass a custom type as a parameter in a method and use it to read JSON from an external API? So if I had this:

trait ApiInfo
case class SunInfoResults(sunrise: String, sunset: String, solar_noon: String, day_length: Long, civil_twilight_begin: String, civil_twilight_end: String, nautical_twilight_begin: String, nautical_twilight_end: String, astronomical_twilight_begin: String, astronomical_twilight_end: String)
case class SunInfo(results: SunInfoResults, status: String) extends ApiInfo
case class TvInfo(url: String, name: String, gender: String, culture: String, born: String, died: String, titles: Array[String], aliases: Array[String], father: String, mother: String, spouse: String, allegiances: Array[String], books: Array[String], povBooks: Array[String], tvSeries: Array[String], playedBy: Array[String]) extends ApiInfo

Before making the service call to the external API I need to declare an implicit to serialize the JSON . So how would I designate the class that this needs to map to (using JSON automated mapping in Play 2.5 )? I'm sure that this must be possible as Scala is built on the concept of reducing duplicate code - which I would otherwise have to do without such a solution. This is the line that I have had trouble passing any custom types into:

implicit val infoReads = Json.reads[p] // where p is SunInfo or TvInfo

Just to also include after doing some research on the subject of types; I am wondering if I would have to use phantom types as the class is not instantiated until it is correctly mapped to the JSON response.

I think I understand your question, let me know otherwise: Play can't automap InfoReads because its missing a Json converter for one of its property types SunInfoResults ?

The Play JSON API provides implicit Reads/Writes for most basic types (int, boolean). To convert your own models to and from JsValues, you must define implicit Reads and Writes converters and provide them in scope. So If you are using Automated Conversion for SunInfo :

implicit val sunInfoReads: Reads[SunInfo] = Json.reads[SunInfo]

Play will be able to read property results: SunInfoResults as long as you have implicit Reads defined for the custom data type SunInfoResults within scope

implicit val sunInfoResultsReads: Reads[SunInfoResults] = Json.reads[SunInfoResults]

If I don't need to define any custom Reads/Writes or add validation, I'll often just use the formatter in the case class's companion object, which will automatically be imported into scope where SunInfoResult is used:

case class SunInfoResults(sunrise: String, sunset: String, solar_noon: String, day_length: Long, civil_twilight_begin: String, civil_twilight_end: String, nautical_twilight_begin: String, nautical_twilight_end: String, astronomical_twilight_begin: String, astronomical_twilight_end: String)

object SunInfoResults {
  implicit val sunInfoResultsFormat = Json.format[SunInfoResults]
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM