当X从Y扩展而Y是trait时,如何在Play JSON中定义Y和List[X]的格式?
我不能在特定情况下转换列表:当类型是从trait扩展而来时 当我可以转换时:当X从Y扩展而Y是trait时,如何在Play JSON中定义Y和List[X]的格式?,json,scala,playframework,play-json,Json,Scala,Playframework,Play Json,我不能在特定情况下转换列表:当类型是从trait扩展而来时 当我可以转换时: import play.api.libs.functional.syntax_ 导入play.api.libs.json_ 密封特征项 案例类Id(Id:Long)扩展项目 案例类MyList(列表:列表[Id]) 对象MyFormat{ 隐式lazy val idFormat=Json.format[Id] 隐式lazy val myListFormat=Json.format[MyList] } 当我无法转换时:
import play.api.libs.functional.syntax_
导入play.api.libs.json_
密封特征项
案例类Id(Id:Long)扩展项目
案例类MyList(列表:列表[Id])
对象MyFormat{
隐式lazy val idFormat=Json.format[Id]
隐式lazy val myListFormat=Json.format[MyList]
}
当我无法转换时:
密封特征项
案例类Id(Id:Long)扩展项目
案例类MyList(列表:列表[Id])
对象MyFormat{
隐式lazy val itemFormat=新格式[项目]{
重写def写入(o:Item):JsValue=o匹配{
案例一:Id=>idFormat.writes(i)
}
覆盖def读取(json:JsValue):JsResult[Item]={
idFormat.reads(json)
}
}
隐式lazy val idFormat=Json.format[Id]
隐式lazy val myListFormat=Json.format[MyList]
}
错误:
错误:(33,49)隐式作用域中的scala.collection.immutable.List[Main2.Id]没有play.api.libs.json.Format的实例可用(提示:如果在同一文件中声明,请确保之前已声明)
隐式lazy val myListFormat=Json.format[MyList]
为什么我不能在第二种情况下格式化
如果我为列表添加格式化程序:
implicit lazy val idsFormat=Json.format[List[Id]]
然后我得到了错误:(33,46)隐式作用域中的scala.collection.immutable.Nil没有可用的读取实例(提示:如果在同一个文件中声明,请确保在前面声明)
隐式惰性val idsFormat=Json.format[List[Id]]
附言:
我找到的唯一解决方案是:
列表[Id]
Id的格式
如果play JSON具有自动/半自动编解码器实例派生功能,那么它将使用隐式来启用这种机制。这意味着复杂事物的编解码器应该在其组件之后引入 在您的例子中,play JSON似乎试图为List和case类i派生编解码器。E至于
List(a1,List(a2,…,List(an,Nil))
当它点击Nil时,它不知道如何为它派生编解码器
我相信您不希望列表编码为折叠对象链,而是编码为JSON数组
然后,您应该在播放源中搜索默认的List[T]
codec,并尝试通过专门化Id
来使用它
调试缺少隐式的通用工具是编译器选项“-Xlog implicits”。它将把所有失败的隐式搜索记录到控制台,并且可以找出这些消息缺少的内容
强烈建议在使用广泛使用此功能的库之前了解隐式作品
最后,但并非最不重要的是:
你试过使用吗?它为密封特征族和标准scala类自动和半自动JSON派生。它甚至有一个游戏框架。Circe派生消除了编写编解码器代码的最头痛的问题,但需要对隐式优先级有很强的了解才能正常工作。对其工作方式进行了描述和分析
如果没有足够的标准版本,您也可以尝试为play json创建自己的派生版本。谢谢,我稍后会尝试
def flatten[T](xs: Seq[JsResult[T]]): JsResult[List[T]] = {
val (ss: Seq[JsSuccess[T]], fs: Seq[JsError]) = xs.partition(_.isSuccess)
if (fs.isEmpty) JsSuccess(ss.map(_.get).toList) else fs.head
}