scala spray-json 如何解析一个复杂的 数组JSON
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了scala spray-json 如何解析一个复杂的 数组JSON相关的知识,希望对你有一定的参考价值。
微信公众平台 获取 用户列表的解析 JSON 如下
"user_info_list":[
"city":"Hangzhou","subscribe":1,"country":"China","nickname":"allen",
"city":"Haidian","subscribe":1,"country":"China","nickname":"钱钱",
"city":"浦东","subscribe":1,"country":"上海市","nickname":"张三"]
怎么用
case class userInfo(
subscribe: Int,
nickname: String,
city: String,
country: String
)
case class userresult(user_info_list: List[userInfo])
object MyuserresultJsonProtocol extends DefaultJsonProtocol
implicit object userresultFormat extends RootJsonFormat[userresult]
import cc.meione.model.request.weixinsend.MyUserInfoJsonProtocol._
import DefaultJsonProtocol._
def write(item: userresult) =
JsObject(
"user_info_list" -> JsArray(item.user_info_list.map(_.toJson).toVector)
)
def read(value: JsValue): userresult = ???
的 read 写法 把 JSON 转成 对象 蟹蟹
implicit val userFormat = jsonFormat4(userInfo)
implicit object UserresultFormat extends RootJsonFormat[userresult]
def write(c: userresult) = JsObject(
"user_info_list" -> JsArray(c.user_info_list.map(_.toJson).toVector)
)
def read(value: JsValue) =
value.asJsObject.getFields("user_info_list") match
case Seq(JsArray(elems)) =>
userresult(elems.map(_.convertTo[userInfo]).toList)
case _ => throw new DeserializationException("userresult expected")
测试截图
Scala,spray-json:通用枚举 json 格式
【中文标题】Scala,spray-json:通用枚举 json 格式【英文标题】:Scala, spray-json: universal enumeration json formatting 【发布时间】:2018-03-18 15:22:36 【问题描述】:我有这样的模型:两个枚举和一个案例类,其中包含这些枚举类型的两个字段:
// see later, why objects are implicit
implicit object Fruits extends Enumeration
val Apple = Value("apple")
val Orange = Value("orange")
implicit object Vegetables extends Enumeration
val Potato = Value("potato")
val Cucumber = Value("cucumber")
val Tomato = Value("tomato")
type Fruit = Fruits.Value
type Vegetable = Vegetables.Value
case class Pair(fruit: Fruit, vegetable: Vegetable)
我想使用 spray-json 向/从 Pairs 解析/生成 JSON。我不想为水果和蔬菜单独声明JsonFormat
s。所以,我想做这样的事情:
import spray.json._
import spray.json.DefaultJsonProtocol._
// enum is implicit here, that's why we needed implicit objects
implicit def enumFormat[A <: Enumeration](implicit enum: A): RootJsonFormat[enum.Value] =
new RootJsonFormat[enum.Value]
def read(value: JsValue): enum.Value = value match
case JsString(s) =>
enum.withName(s)
case x =>
deserializationError("Expected JsString, but got " + x)
def write(obj: enum.Value) = JsString(obj.toString)
// compilation error: couldn't find implicits for JF[Fruit] and JF[Vegetable]
implicit val pairFormat = jsonFormat2(Pair)
// expected value:
// spray.json.JsValue = "fruit":"apple","vegetable":"potato"
// but actually doesn't even compile
Pair(Fruits.Apple, Vegetables.Potato).toJson
遗憾的是,enumFormat
不会为 jsonFormat2
生成隐式值。如果我在 pairFormat 之前手动为水果和蔬菜格式编写两个隐式声明,那么 json marshalling 就可以了:
implicit val fruitFormat: RootJsonFormat[Fruit] = enumFormat(Fruits)
implicit val vegetableFormat: RootJsonFormat[Vegetable] = enumFormat(Vegetables)
implicit val pairFormat = jsonFormat2(Pair)
// "fruit":"apple","vegetable":"potato", as expected
Pair(Fruits.Apple, Vegetables.Potato).toJson
那么,两个问题:
如何摆脱这些fruitFormat
和vegetableFormat
声明?
理想情况下,最好不要将枚举对象设为隐式,同时保持enumFormat
函数的通用性。有没有办法做到这一点?也许,使用scala.reflect
包或类似的东西。
【问题讨论】:
【参考方案1】:您只需将enum.Value
替换为A#Value
。
查看spray-json #200,您可以找到定义明确的隐式enumFormat
的示例,稍作修改以利用隐式enu
检索:
implicit def enumFormat[T <: Enumeration](implicit enu: T): RootJsonFormat[T#Value] =
new RootJsonFormat[T#Value]
def write(obj: T#Value): JsValue = JsString(obj.toString)
def read(json: JsValue): T#Value =
json match
case JsString(txt) => enu.withName(txt)
case somethingElse => throw DeserializationException(s"Expected a value from enum $enu instead of $somethingElse")
【讨论】:
【参考方案2】:你不能,Scala 不允许隐式链接,因为它会导致组合爆炸,使编译器太慢。
见https://docs.scala-lang.org/tutorials/FAQ/chaining-implicits.html
Scala 不允许发生两次这样的隐式转换,因此不能使用隐式 A 到 B 和另一个隐式 B 到 C 从 A 到 C。
您必须为要使用的每个 T
显式生成一个 JsonFormat[T]
。
【讨论】:
以上是关于scala spray-json 如何解析一个复杂的 数组JSON的主要内容,如果未能解决你的问题,请参考以下文章