关键词:
【中文标题】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]
。
【讨论】:
如何使用 AKKA-HTTP、spray-json、oauth2 和 slick 优化 scala REST api?
】如何使用AKKA-HTTP、spray-json、oauth2和slick优化scalaRESTapi?【英文标题】:HowtooptimizescalaRESTapiusingAKKA-HTTP,spray-json,oauth2andslick?【发布时间】:2017-01-3111:11:31【问题描述】:我使用AKKA-HTTP、spray-json和Slick在scala中创建了一个RESTapi。对... 查看详情
如何在 Scala 3 枚举上进行模式匹配
...如:objmatchcasee:Enumeration=>...caseother=>...在Scala3中没有通用接口,如 查看详情
Scala 类型类模式和泛型方法
...述】:我正在尝试编写一个通用提取器,用于使用spray和spray-json解析jsonPOST正文。但是,我很难让它与多个模型一起使用。这是服务对象中的case语句:importMyJsonProtocol._...defreceive=casePost(R 查看详情
spray-json
spray-json是一个轻量级的,简介的和高效的使用Scala实现的json它拥有以下特征:一个简单不可变的模型的json语言元素一个高效的json解析器可选择既紧凑又漂亮的json到string的打印(格式化输出)基于类的自定义对象的(反)序列化(没... 查看详情
scala枚举:enumeration概述
SparkScala枚举*Java中的那套枚举并不能直接使用到Scala中*Scala中的枚举使用轻量级Enumeration进行实现*Scala中的枚举其实是一个伴随对象*Scala中的枚举没有方法重写功能*Scala中的枚举其实都是Enumeration.Value这个对象和Java和C++不同,Scala... 查看详情
Scala 3枚举方法覆盖
】Scala3枚举方法覆盖【英文标题】:Scala3enummethodoverride【发布时间】:2021-07-1815:48:22【问题描述】:有没有办法像在Java中一样覆盖Scala3枚举中的方法?publicenumTestONE@Overridepublicintcalc()return1;,TWO@Overridepublicintcalc()return2;;publicabstracti... 查看详情
scala.的enumeration枚举示例(转)
简介 在scala中没有枚举类型,但在标准类库中提供了Enumeration类来产出枚举。扩展Enumeration类后,调用value方法类初始化枚举中的可能值。 内部类value实际上是一个抽象类,真正创建的是val。因为实际上是Val,所以可以为Va... 查看详情
在scala 3中获取枚举的名称?
】在scala3中获取枚举的名称?【英文标题】:Getnameoftheenuminscala3?【发布时间】:2022-01-1216:27:51【问题描述】:Java枚举有name()方法,但scala3没有。如何在scala3中获取枚举的名称?enumColor:caseRed,Green,Blue【问题讨论】:【参考方案1... 查看详情
spark的枚举类型实例!scala的枚举。
Spark的枚举类型实例!scala的枚举。Enumeration定义:[deploy] SparkSubmitAction { = Value = Value}Enumeration使用:appArgs. { SparkSubmitAction.=> ( 查看详情
scala自定义实现枚举
参考技术Ajava使用枚举类型,所以不用scala但是没有枚举类型,如果项目中需要用到枚举或者类似枚举。scala就需要使用其他方式来实现。基本来说有三种第一种,就是在项目中单独写一个java文件,在文件中声明枚举类型,然后... 查看详情
如何在 SORM 中添加 Scala 枚举?
】如何在SORM中添加Scala枚举?【英文标题】:HowtoaddScalaEnumerationinSORM?【发布时间】:2014-08-2813:38:55【问题描述】:如何在SORM中添加枚举?我有这个枚举:objectRoutineTypeextendsEnumerationvalTimeRoutine,SetRoutine=Value并在DB对象中添加实体... 查看详情
Scala:继承的枚举对象不满足父特征
】Scala:继承的枚举对象不满足父特征【英文标题】:Scala:Inheritedenumobjectdoesn\'tsatisfyparenttrait【发布时间】:2021-04-2017:25:30【问题描述】:我正在尝试在方法中使用Enumeration对象。枚举对象从特征扩展而来,该方法将特征作为参... 查看详情
python枚举是不是有等效的Scala?
】python枚举是不是有等效的Scala?【英文标题】:IsthereaScalaequivalentforthepythonenumerate?python枚举是否有等效的Scala?【发布时间】:2011-09-2302:36:24【问题描述】:我想要方便fori,lineinenumerate(open(sys.argv[1])):printi,line在Scala中执行以下操... 查看详情
Scala模式匹配Java枚举值
】Scala模式匹配Java枚举值【英文标题】:ScalapatternmatchingJavaenumvalue【发布时间】:2014-04-1011:30:27【问题描述】:我有我的java枚举,例如:FOO("foo")、BAR("bar")...我有一个getValue()方法来返回枚举的值"foo"和"... 查看详情
scala定义复杂枚举(代码片段)
通常我们需要枚举参数不止两个,Scala提供的枚举类最多定义两个参数:id:Int与name:String。不能满足我们通常要求。1objectBaseEntryEnumextendsEnumeration2typeBaseEntryEnum=Value3//item_base类别4valITEM_TYPE_PURCHASE_CENTER=Value(31,"采购中心")5valITEM_TYP 查看详情
java示例代码_从Java传递Scala枚举
java示例代码_从Java传递Scala枚举 查看详情
scala反射获取枚举值的类
】scala反射获取枚举值的类【英文标题】:scalareflectiongetclassofenumarationvalue【发布时间】:2017-11-0712:22:40【问题描述】:假设我们有classUser(valname:String,valrole:UserRole.Value)classUserRoleextendsEnumerationvalAdmin,User=Valuevalu=newUser("root",Us 查看详情
Circe 和 Scala 的枚举类型
】Circe和Scala的枚举类型【英文标题】:CirceandScala\'sEnumerationtype【发布时间】:2017-06-2310:44:36【问题描述】:我正试图将我的头包裹在Circe周围。所以,这是我得到的模型:objectGenderextendsEnumerationtypeGender=ValuevalMale,Female,Unisex,Unknow... 查看详情