Swagger-play2:如何通过@ApiImplicitParams允许对象数组作为Swagger UI输入?
你遇到的ClassNotFoundException: models.Message.EmailMessage问题,本质是Scala嵌套类在JVM上的命名规则和你在Swagger注解中指定的dataType不匹配导致的。
问题根源
Scala中,定义在object内部的case class会被编译成JVM层面的内部类,它的全限定类名会包含$符号,而不是你写的.。也就是说,你的EmailMessage实际的类名是models.Message$EmailMessage,而不是models.Message.EmailMessage,这就导致Swagger在加载类时找不到对应的字节码文件。
解决方案
方案1:修正ApiImplicitParam中的dataType值
直接把注解里的dataType改成JVM实际的类名:
@ApiImplicitParams(Array( new ApiImplicitParam(value = "EmailMessage", dataType = "models.Message$EmailMessage", paramType = "body", name = "body", required = true) ))
不过这种写法依赖Scala的编译细节,可读性稍差,不是最优解。
方案2:将EmailMessage改为顶层类(推荐)
把EmailMessage从Message object中移出来,变成独立的顶层类,这样类的全限定名更清晰,也符合Swagger的常规识别逻辑:
package models import io.swagger.annotations.{ApiModel, ApiModelProperty} import play.api.data.Form import play.api.data.Forms.{mapping, nonEmptyText, seq} import play.api.libs.json.{Json, Writes} import spray.json.DefaultJsonProtocol @ApiModel(value = "EmailMessage") case class EmailMessage( @(ApiModelProperty@field)(position = 1, dataType = "array", required = true) emails: Seq[String], @(ApiModelProperty@field)(position = 2, required = true) message: String ) // 保留原来的Message object用于JSON协议等 object Message extends DefaultJsonProtocol { // 可在此添加JSON格式定义,比如implicit val emailMessageFormat = jsonFormat2(EmailMessage) }
然后修改控制器的注解:
@ApiImplicitParams(Array( new ApiImplicitParam(value = "EmailMessage", dataType = "models.EmailMessage", paramType = "body", name = "body", required = true) ))
方案3:检查Swagger Play模块版本兼容性
确保你使用的play-swagger模块版本和当前Play框架、Scala版本匹配。比如如果是Play 2.8+,要使用对应的最新版play-swagger,版本不兼容也可能导致类加载时的异常。
方案4:验证编译后的类文件
执行compile命令后,检查target/scala-{your-scala-version}/classes/models/目录下是否存在对应的类文件:
- 如果是嵌套类,应该有
Message$EmailMessage.class - 如果是顶层类,应该有
EmailMessage.class
确保编译过程没有报错,类文件正常生成。
额外提示
如果你的API是接收数组的EmailMessage,记得在ApiImplicitParam的dataType前明确标注数组类型,比如dataType = "List[models.EmailMessage]"(不同Swagger版本写法可能有差异,需根据你使用的版本调整)。
内容的提问来源于stack exchange,提问作者Shashi Shekhar

