Play JSON密封特质类型的隐式解析问题
问题描述
定义了一个被CaseClass1、CaseClass2两个样例类实现的密封特质MySealedTrait,并编写了针对该特质的隐式Writes:
implicit val myCaseClassWrites: Writes[MySealedTrait] = Writes { case CaseClass1(a, b, c) => Json.toJson( a, b, c ) case CaseClass2(a, b, c, d) => Json.toJson( a, b, c, d ) }
在控制器中以JSON形式返回响应时,编译报错:
No Json serializer found for type com.mypackage.CaseClass2. Try to implement an implicit Writes or Format for this type
为CaseClass2编写显式Writes后,问题解决:
implicit val caseClass2JSONWrites: Writes[CaseClass2] = Writes { caseClass2 => Json.toJson(caseClass2.a, caseClass2.b, caseClass2.c, caseClass2.d ) }
请问该现象的原因是什么?
原因分析
- Scala隐式解析优先匹配最具体的类型:当直接返回
CaseClass2类型的实例时,编译器会优先寻找针对CaseClass2的隐式Writes,而非向上查找父特质MySealedTrait的Writes。最初仅定义了父特质的序列化器,导致编译器找不到对应CaseClass2的序列化逻辑,触发报错。 - 父特质的
Writes[MySealedTrait]仅适用于声明为MySealedTrait类型的实例:如果控制器返回值被显式声明为MySealedTrait类型(比如val response: MySealedTrait = CaseClass2(...)),编译器才会使用父特质的Writes。但返回原始CaseClass2类型时,编译器不会自动向上匹配父特质的序列化器。 - 显式添加
Writes[CaseClass2]后,编译器找到了对应具体类型的隐式序列化器,报错消失。另外也可以不用单独编写该序列化器,只要将返回的CaseClass2实例显式转换为MySealedTrait类型,同样能复用父特质的Writes逻辑。
内容的提问来源于stack exchange,提问作者joesan
相关产品推荐
相关产品推荐

