Scala中值类的隐式Json格式化程序



我有许多值类,它们组成了一个更大的对象事例类。

final case class TopLevel(
foo: Foo,
bar: Bar
)
final case class Foo(foo: String) extends AnyVal
final case class Bar(bar: String) extends AnyVal
object Foo {
implicit val format = Json.valueFormat[Foo]
}
object Bar {
implicit val format = Json.valueFormat[Bar]
}
object TopLevel {
implicit val TopLevelFormat: OFormat[TopLevel] = Json.format[TopLevel]
}

这很好,但当顶级case类有许多参数时,构造对象很快就会堆积起来。我试着含蓄地这样做,例如

object Format {
implicit def jsonFormatter[A](): Format[A] = Json.valueFormat[A]
}

但我有

scala.ScalaReflectionException: <none> is not a method

formatvalueFormat是宏(实际上不是它们自己,而是它们称为宏(。所以你不能随便叫他们。Json.valueFormat[A]正在尝试扩展其中A还不是值类而是抽象类型(类型参数(。如果你想推迟宏的扩展,你可以让你的隐式宏

// in a different subproject
import play.api.libs.json.{Format, OFormat}
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
object Format {
implicit def valueFormat[A]: Format[A] = macro MacroImpl.valueFormatImpl[A]
implicit def format[A]: OFormat[A] = macro MacroImpl.formatImpl[A]
}
class MacroImpl(val c: whitebox.Context) {
import c.universe._
val json = q"_root_.play.api.libs.json.Json"
def valueFormatImpl[A: WeakTypeTag]: Tree = q"$json.valueFormat[${weakTypeOf[A]}]"
def formatImpl[A: WeakTypeTag]: Tree = q"$json.format[${weakTypeOf[A]}]"
}

现在,您不需要在类或值类的伴随对象中定义隐词。您只需要将隐含词从Format导入到需要它们的

final case class TopLevel(foo: Foo, bar: Bar)
final case class Foo(foo: String) extends AnyVal
final case class Bar(bar: String) extends AnyVal
import Format._
implicitly[Format[Foo]].writes(Foo("a")) // {"foo":"a"}
implicitly[Format[Bar]].writes(Bar("b")) // {"bar":"b"}
implicitly[Format[TopLevel]].writes(TopLevel(Foo("a"), Bar("b"))) // {"foo":{"foo":"a"},"bar":{"bar":"b"}}
implicitly[OFormat[Foo]].writes(Foo("a")) // {"foo":"a"}
implicitly[OFormat[Bar]].writes(Bar("b")) // {"bar":"b"}
implicitly[OFormat[TopLevel]].writes(TopLevel(Foo("a"), Bar("b"))) // {"foo":{"foo":"a"},"bar":{"bar":"b"}}

或者,可以为类或伴随对象定义宏注释。它将在伴随对象内部生成必要的隐词。但我想现在隐式宏比宏注释简单一点。

最新更新