我正在尝试创建内联def来为Scala 3中的任何枚举生成Json编解码器。为此,我需要访问枚举的父代的valueOf方法。inline def gen[T](using JsonCodec[String], T <:< reflect.Enum): JsonCodec[T] = ???
如何才能做到这一点?
阅读评论后,现在我改变了我的代码:
val decoder: JsonDecoder[T] = JsonDecoder[String].mapOrFail(v => Try(${getEnum[T]}(v)).fold(e => Left(e.getMessage), v => Right(v)))
val encoder: JsonEncoder[T] = JsonEncoder[String].contramap(_.toString)
JsonCodec.apply(encoder, decoder)
def getEnum[T: Type](using Quotes): Expr[String => T] =
import quotes.reflect.*
val companion = Ref(TypeTree.of[T].symbol.companionModule)
Select.unique(companion, "valueOf").asExprOf[String => T]
编译器抱怨:
Malformed macro.
Expected the splice ${...} to be at the top of the RHS:
inline def foo(inline x: X, ..., y: Y): Int = ${ impl('x, ... 'y) }
* The contents of the splice must call a static method
* All arguments must be quoted
1条答案
按热度按时间kknvjkwl1#
作为json库,您似乎使用https://zio.github.io/zio-json
宏格式不正确。
预期拼接
${...}
位于RHS顶部我想这个错误是可以理解的。你不应该像那样直接使用宏实现。
您有一个宏(内联方法)
getEnum
及其实现getEnumImpl
(返回Expr
),并且使用getEnum
(而不是getEnumImpl
)或
getEnum
本身是宏实现,您可以在另一个宏实现中使用它现在的错误是
可以用
Apply
PackageSelect.unique
(并用方法替换函数String => T
)。或
此外,为了派生枚举的
JsonCodec
,可以使用Mirror
测试: