我有一大堆案例类,下面只是这些案例类的一个子集:
sealed trait BuiltInType { def id: Int }
case class ZombieType (a: String, id: Int = 0) extends BuiltInType
case class BooleanType (a: Boolean, id: Int = 1) extends BuiltInType
case class ByteType (a: Byte, id: Int = 2) extends BuiltInType
case class UByteType (a: Byte, id: Int = 3) extends BuiltInType
case class Int16Type (a: Int, id: Int = 4) extends BuiltInType
case class UInt16Type (a: Int, id: Int = 5) extends BuiltInType
case class Int32Type (a: Int, id: Int = 6) extends BuiltInType
case class UInt32Type (a: Int, id: Int = 7) extends BuiltInType
case class Int64Type (a: Long, id: Int = 8) extends BuiltInType
case class UInt64Type (a: Long, id: Int = 9) extends BuiltInType
case class FloatType (a: Float, id: Int = 10) extends BuiltInType
case class DoubleType (a: Double, id: Int = 11) extends BuiltInType
case class StringType (a: String, id: Int = 12) extends BuiltInType
case class DateTimeType (a: Long, id: Int = 13) extends BuiltInType // FIXME: Wrong type used, fix it later
case class GuidType (a: UUID, id: Int = 14) extends BuiltInType
case class ByteStringType (a: Vector[Byte], id: Int = 15) extends BuiltInType
case class XmlElementType (a: String, id: Int = 16) extends BuiltInType
case class NodeIdType (a: NodeId, id: Int = 17) extends BuiltInType
case class ExpandedNodeIdType (a: NodeId, id: Int = 18) extends BuiltInType // FIXME: Wrong type used, fix it later
case class StatusCodeType (a: StatusCode, id: Int = 19) extends BuiltInType
case class QualifiedNameType (a: QualifiedName, id: Int = 20) extends BuiltInType
case class LocalizedTextType (a: LocalizedText, id: Int = 21) extends BuiltInType
case class ExtensionObjectType (a: ExtensionObject, id: Int = 22) extends BuiltInType
case class DataValueType (a: DataValue, id: Int = 23) extends BuiltInType
case class VariantType (a: Variant, id: Int = 24) extends BuiltInType
case class DiagnosticInfoType (a: String, id: Int = 25) extends BuiltInType
如您所见,我定义了其他几种复杂类型。例如,有一个名为 Variant 的类型,它本身就是这样的案例类:
sealed trait VariantData
case class SimpleOrder(rows: Vector[BuiltInType]) extends VariantData
case class HigherOrder(matrices: Vector[VariantData]) extends VariantData
case class Variant(data: VariantData)
然后,我像这样定义播放 JSON 所需的所有隐式格式:
implicit val strType = Json.format[StringType]
implicit val guidType = Json.format[GuidType]
implicit val int16Type = Json.format[Int16Type]
implicit val uint64Type = Json.format[UInt64Type]
implicit val int32Type = Json.format[Int32Type]
implicit val int64Type = Json.format[Int64Type]
implicit val uByteTyp = Json.format[UByteType]
implicit val qNameType = Json.format[QualifiedNameType]
implicit val nodeIdTyp = Json.format[NodeIdType]
implicit val locTextTyp = Json.format[LocalizedTextType]
implicit val zombType = Json.format[ZombieType]
implicit val statusCodeTyp = Json.format[StatusCodeType]
implicit val builtInType = Json.format[BuiltInType]
implicit val simpleFmt = Json.format[SimpleOrder]
implicit val higherFmt = Json.format[HigherOrder]
implicit val varDataFmt = Json.format[VariantData]
implicit val varFmt = Json.format[Variant]
我收到此错误:
Error:(66, 43) No instance of Reads is available for domain.CommonTypes.VariantType in the implicit scope (Hint: if declared in the same file, make sure it's declared before)
implicit val builtInType = Json.format[BuiltInType]
所以我像这样更改了隐式的顺序:
implicit val simpleFmt = Json.format[SimpleOrder]
implicit val higherFmt = Json.format[HigherOrder]
implicit val varDataFmt = Json.format[VariantData]
implicit val varFmt = Json.format[Variant]
implicit val strType = Json.format[StringType]
implicit val guidType = Json.format[GuidType]
implicit val int16Type = Json.format[Int16Type]
implicit val uint64Type = Json.format[UInt64Type]
implicit val int32Type = Json.format[Int32Type]
implicit val int64Type = Json.format[Int64Type]
implicit val uByteTyp = Json.format[UByteType]
implicit val qNameType = Json.format[QualifiedNameType]
implicit val nodeIdTyp = Json.format[NodeIdType]
implicit val locTextTyp = Json.format[LocalizedTextType]
implicit val zombType = Json.format[ZombieType]
implicit val statusCodeTyp = Json.format[StatusCodeType]
implicit val builtInType = Json.format[BuiltInType]
但是现在,我收到此错误:
Error:(53, 41) No instance of play.api.libs.json.Format is available for scala.collection.immutable.Vector[domain.CommonTypes.BuiltInType] in the implicit scope (Hint: if declared in the same file, make sure it's declared before)
implicit val simpleFmt = Json.format[SimpleOrder]
所以我现在的问题是,这是一个订购问题还是我错过了一些东西,因为这里的抱怨是它期待一个
矢量[内置类型]
还是循环依赖导致了这个问题?
通常,您始终可以解决以下排序问题:
把
formats
放在companion-objects
.
请参阅下面的示例。
为了简化您的工作sealed traits
我会使用play-json 派生的编解码器
进口:
import play.api.libs.json._
import julienrf.json.derived
很酷的是你只需要format
trait
,它的所有subclasses
都会自动完成:
implicit val jsonFormat: OFormat[VariantData] = derived.oformat[VariantData]()
implicit val jsonFormat: OFormat[BuiltInType] = derived.oformat[BuiltInType]()
format
代码略有不同。
为了说明这如何简化代码,这里有Dmytro的例子:
import play.api.libs.json._
import julienrf.json.derived
sealed trait BuiltInType { def id: Int }
case class StringType(a: String, id: Int = 12) extends BuiltInType
case class ByteStringType(a: Seq[Byte], id: Int = 15) extends BuiltInType
case class VariantType(a: Variant, id: Int = 24) extends BuiltInType
object BuiltInType {
implicit val jsonFormat: OFormat[BuiltInType] = derived.oformat[BuiltInType]()
}
sealed trait VariantData
case class SimpleOrder(rows: Seq[BuiltInType]) extends VariantData
case class HigherOrder(matrices: Seq[VariantData]) extends VariantData
object VariantData {
implicit val jsonFormat: OFormat[VariantData] = derived.oformat[VariantData]()
}
case class Variant(data: VariantData)
object Variant {
implicit val jsonFormat: OFormat[Variant] = derived.oformat[Variant]()
}
val json = Json.toJson(VariantType(Variant(SimpleOrder(Seq(StringType("aaa"))))): BuiltInType)
println(json) //{"a":{"data":{"_type":"App.SimpleOrder","rows":[{"a":"aaa","_type":"App.StringType","id":12}]}},"_type":"App.VariantType","id":24}
有了你的例子,差异会更大。
不要忘记指定隐式类型并重新排列隐式,以便没有警告
Warning: Reference to uninitialized value ...
implicit val ...
以下代码似乎适用于 Scala 2.13.0/2.12.8 + play-json 2.7.4
import play.api.libs.json._
object App {
sealed trait BuiltInType { def id: Int }
case class StringType (a: String, id: Int = 12) extends BuiltInType
case class ByteStringType (a: Vector[Byte], id: Int = 15) extends BuiltInType
case class VariantType (a: Variant, id: Int = 24) extends BuiltInType
sealed trait VariantData
case class SimpleOrder(rows: Vector[BuiltInType]) extends VariantData
case class HigherOrder(matrices: Vector[VariantData]) extends VariantData
case class Variant(data: VariantData)
implicit val strType: OFormat[StringType] = Json.format[StringType]
implicit val byteStrType: OFormat[ByteStringType] = Json.format[ByteStringType]
implicit val varDataFmt: OFormat[VariantData] = Json.format[VariantData]
implicit val builtInType: OFormat[BuiltInType] = Json.format[BuiltInType]
implicit val simpleFmt: OFormat[SimpleOrder] = Json.format[SimpleOrder]
implicit val higherFmt: OFormat[HigherOrder] = Json.format[HigherOrder]
implicit val varFmt: OFormat[Variant] = Json.format[Variant]
implicit val varType: OFormat[VariantType] = Json.format[VariantType]
val json = Json.toJson(VariantType(Variant(SimpleOrder(Vector(StringType("aaa"))))): BuiltInType)
println(json)//{"a":{"data":{"_type":"App.SimpleOrder","rows":[{"a":"aaa","_type":"App.StringType","id":12}]}},"_type":"App.VariantType","id":24}
}