Skip to content

Commit c9b76bd

Browse files
committed
Fix computed Scala 3 jsonHint derivation
1 parent 8905e47 commit c9b76bd

2 files changed

Lines changed: 32 additions & 12 deletions

File tree

zio-json/shared/src/main/scala-3/zio/json/macros.scala

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,13 @@ private[json] final case class SumMeta(
231231
// =======================================================================================
232232
private[json] object MacroHelpers {
233233

234+
private def extractJsonHintName(using Quotes)(annotation: quotes.reflect.Term): Option[Expr[String]] = {
235+
annotation.asExpr match {
236+
case '{ new zio.json.jsonHint($name: String) } => Some(name)
237+
case _ => None
238+
}
239+
}
240+
234241
// =====================================================================================
235242
// Consolidated single-pass metadata extraction macros
236243
// =====================================================================================
@@ -349,21 +356,21 @@ private[json] object MacroHelpers {
349356

350357
val subTypes = leafTypes(sym)
351358
val infos = subTypes.map { subSym =>
352-
val hintAnnotation = subSym.annotations.map(_.asExpr).collectFirst {
353-
case '{ new zio.json.jsonHint(${ Expr(name) }: String) } => name
354-
}
359+
val hintAnnotation = subSym.annotations.collectFirst(Function.unlift(extractJsonHintName))
355360
val hasHint = hintAnnotation.isDefined
356361
val hintName = hintAnnotation.getOrElse {
357-
if (subSym.flags.is(Flags.Module)) subSym.companionModule.name
358-
else subSym.name
362+
Expr(
363+
if (subSym.flags.is(Flags.Module)) subSym.companionModule.name
364+
else subSym.name
365+
)
359366
}
360367
val isObj = subSym.flags.is(Flags.Module) ||
361368
(subSym.flags.is(Flags.Enum) && subSym.flags.is(Flags.JavaStatic)) ||
362369
(subSym.flags.is(Flags.Enum) && subSym.flags.is(Flags.Case) && subSym.caseFields.isEmpty && !subSym.flags.is(
363370
Flags.Trait
364371
))
365372
val hasFields = subSym.caseFields.nonEmpty
366-
(Expr(hintName), Expr(isObj), Expr(hasFields), Expr(hasHint))
373+
(hintName, Expr(isObj), Expr(hasFields), Expr(hasHint))
367374
}
368375
val subtypeInfoExpr = '{
369376
Array(${
@@ -502,21 +509,21 @@ private[json] object MacroHelpers {
502509

503510
val subTypes = leafTypes(sym)
504511
val infos = subTypes.map { subSym =>
505-
val hintAnnotation = subSym.annotations.map(_.asExpr).collectFirst {
506-
case '{ new zio.json.jsonHint(${ Expr(name) }: String) } => name
507-
}
512+
val hintAnnotation = subSym.annotations.collectFirst(Function.unlift(extractJsonHintName))
508513
val hasHint = hintAnnotation.isDefined
509514
val hintName = hintAnnotation.getOrElse {
510-
if (subSym.flags.is(Flags.Module)) subSym.companionModule.name
511-
else subSym.name
515+
Expr(
516+
if (subSym.flags.is(Flags.Module)) subSym.companionModule.name
517+
else subSym.name
518+
)
512519
}
513520
val isObj = subSym.flags.is(Flags.Module) ||
514521
(subSym.flags.is(Flags.Enum) && subSym.flags.is(Flags.JavaStatic)) ||
515522
(subSym.flags.is(Flags.Enum) && subSym.flags.is(Flags.Case) && subSym.caseFields.isEmpty && !subSym.flags.is(
516523
Flags.Trait
517524
))
518525
val hasFields = subSym.caseFields.nonEmpty
519-
(Expr(hintName), Expr(isObj), Expr(hasFields), Expr(hasHint))
526+
(hintName, Expr(isObj), Expr(hasFields), Expr(hasHint))
520527
}
521528
'{
522529
Array(${

zio-json/shared/src/test/scala-3/zio/json/DecoderVersionSpecificSpec.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,19 @@ object DecoderVersionSpecificSpec extends ZIOSpecDefault {
147147
assertTrue("""{"$type":"Qux"}""".fromJson[Foo] == Right(Foo.Qux)) &&
148148
assertTrue("""{"$type":"Barrr"}""".fromJson[Foo] == Right(Foo.Bar))
149149
},
150+
test("Derives for a sum sealed trait Enumeration type with computed jsonHint") {
151+
@jsonDiscriminator("$type")
152+
sealed trait Foo
153+
object Foo:
154+
@jsonHint("Bar" + "rr")
155+
case object Bar extends Foo
156+
case object Baz extends Foo
157+
158+
given JsonCodec[Foo] = DeriveJsonCodec.gen[Foo]
159+
160+
assertTrue((Foo.Bar: Foo).toJson == """{"$type":"Barrr"}""") &&
161+
assertTrue("""{"$type":"Barrr"}""".fromJson[Foo] == Right(Foo.Bar))
162+
},
150163
test("skip JSON encoded in a string value") {
151164
@jsonDiscriminator("type")
152165
sealed trait Example derives JsonDecoder {

0 commit comments

Comments
 (0)