diff --git a/play-json/shared/src/main/scala-3/play/api/libs/json/JsMacroImpl.scala b/play-json/shared/src/main/scala-3/play/api/libs/json/JsMacroImpl.scala index 7e2ed403..28ac5ac7 100644 --- a/play-json/shared/src/main/scala-3/play/api/libs/json/JsMacroImpl.scala +++ b/play-json/shared/src/main/scala-3/play/api/libs/json/JsMacroImpl.scala @@ -329,7 +329,13 @@ object JsMacroImpl { // TODO: debug val default: Option[Expr[t]] = compCls.declaredMethod(f"$$lessinit$$greater$$default$$" + (i + 1)).headOption.collect { case defaultSym if sym.flags.is(Flags.HasDefault) => - Ref(tpr.typeSymbol.companionModule).select(defaultSym).asExprOf[t] + val select = Select(Ref(tpr.typeSymbol.companionModule), defaultSym) + val tree = + TypeRepr.of[T].typeArgs match { + case Nil => select + case typeArgs => select.appliedToTypes(typeArgs) + } + tree.asExprOf[t] } ReadableField(sym, i, pt, default) diff --git a/play-json/shared/src/test/scala/play/api/libs/json/MacroSpec.scala b/play-json/shared/src/test/scala/play/api/libs/json/MacroSpec.scala index b03edc13..0a6ff1d5 100644 --- a/play-json/shared/src/test/scala/play/api/libs/json/MacroSpec.scala +++ b/play-json/shared/src/test/scala/play/api/libs/json/MacroSpec.scala @@ -518,6 +518,26 @@ class MacroSpec extends AnyWordSpec with Matchers with org.scalatestplus.scalach nesting.Test.format.reads(expectedJson).mustEqual(JsSuccess(expected)) } + + "handle case class with generic type and default field" in { + implicit val format: Format[GenericCaseClassWithDefault[Int]] = Json.format[GenericCaseClassWithDefault[Int]] + + val expected = GenericCaseClassWithDefault(3) + val expectedJson = Json.obj("data" -> 3, "descr" -> "something") + + Json.toJson(GenericCaseClassWithDefault(3)).mustEqual(expectedJson) + Json.fromJson(expectedJson).mustEqual(JsSuccess(expected)) + } + + "handle case class with generic type and overridden default field" in { + implicit val format: Format[GenericCaseClassWithDefault[Int]] = Json.format[GenericCaseClassWithDefault[Int]] + + val expected = GenericCaseClassWithDefault(3, "foo") + val expectedJson = Json.obj("data" -> 3, "descr" -> "foo") + + Json.toJson(GenericCaseClassWithDefault(3, "foo")).mustEqual(expectedJson) + Json.fromJson(expectedJson).mustEqual(JsSuccess(expected)) + } } } @@ -624,4 +644,9 @@ object MacroSpec { Json.format[Test] } } + + case class GenericCaseClassWithDefault[A]( + data: A, + descr: String = "something" + ) }