Scala中format参数引发编译错误的解决方案问询
问题:openapi-generator生成的Scala代码因参数名冲突导致编译错误
我用openapi-generator生成了Scala代码,调用其中的registerApiOauth2方法时出现编译错误,具体代码和报错信息如下:
生成的AuthTokensApi代码
import examples.openverse.model.{InlineObject, OAuth2RegistrationSuccessful} import examples.openverse.core.JsonSupport._ import sttp.client3._ import sttp.model.Method object AuthTokensApi { def apply(baseUrl: String = "https://api.openverse.engineering/v1") = new AuthTokensApi(baseUrl) } def registerApiOauth2(format: String, data: InlineObject ): Request[Either[ResponseException[String, Exception], OAuth2RegistrationSuccessful], Any] = basicRequest .method(Method.POST, uri"$baseUrl/auth_tokens/register/?format=${ format }") .contentType("application/json") .body(data) .response(asJson[OAuth2RegistrationSuccessful])
JsonSupport实现代码
object JsonSupport extends SttpJson4sApi { def enumSerializers: Seq[Serializer[_]] = Seq[Serializer[_]]() :+ new EnumNameSerializer(AudioReportRequestEnums.Reason) :+ new EnumNameSerializer(ImageReportRequestEnums.Reason) private class EnumNameSerializer[E <: Enumeration: ClassTag](enum: E) extends Serializer[E#Value] { import JsonDSL._ val EnumerationClass: Class[E#Value] = classOf[E#Value] def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), E#Value] = { case (t @ TypeInfo(EnumerationClass, _), json) if isValid(json) => json match { case JString(value) => enum.withName(value) case value => throw new MappingException(s"Can't convert $value to $EnumerationClass") } } private[this] def isValid(json: JValue) = json match { case JString(value) if enum.values.exists(_.toString == value) => true case _ => false } def serialize(implicit format: Formats): PartialFunction[Any, JValue] = { case i: E#Value => i.toString } } implicit val format: Formats = DefaultFormats ++ enumSerializers ++ DateSerializers.all implicit val serialization: org.json4s.Serialization = org.json4s.jackson.Serialization }
编译报错信息
No implicit view available from examples.openverse.model.InlineObject => sttp.client3.BasicRequestBody. .body(data)
No org.json4s.Formats found. Try to bring an instance of org.json4s.Formats in scope or use the org.json4s.DefaultFormats. .response(asJson[OAuth2RegistrationSuccessful])
问题根源
方法参数名format和JsonSupport中定义的隐式值format: Formats重名,导致局部参数遮蔽了全局的隐式实例,使得sttp无法找到将InlineObject转换为请求体所需的隐式转换,同时asJson也找不到需要的Formats隐式值。
解决方案
1. 重命名方法参数,保留查询参数名
将方法的参数名改为非冲突的名称(比如formatParam),但在uri中仍然使用format作为查询参数名:
def registerApiOauth2(formatParam: String, data: InlineObject ): Request[Either[ResponseException[String, Exception], OAuth2RegistrationSuccessful], Any] = basicRequest .method(Method.POST, uri"$baseUrl/auth_tokens/register/?format=${formatParam}") .contentType("application/json") .body(data) .response(asJson[OAuth2RegistrationSuccessful])
2. 显式指定隐式参数
在方法签名中显式声明所需的隐式参数,避免局部参数遮蔽全局隐式:
def registerApiOauth2(format: String, data: InlineObject )(implicit jsonFormats: org.json4s.Formats = JsonSupport.format, jsonSerialization: org.json4s.Serialization = JsonSupport.serialization): Request[Either[ResponseException[String, Exception], OAuth2RegistrationSuccessful], Any] = basicRequest .method(Method.POST, uri"$baseUrl/auth_tokens/register/?format=${format}") .contentType("application/json") .body(data) .response(asJson[OAuth2RegistrationSuccessful])
3. 修改JsonSupport中的隐式值名称
将JsonSupport里的隐式format重命名为不冲突的名称(比如jsonFormats),并调整导入语句:
修改后的JsonSupport关键部分:
implicit val jsonFormats: Formats = DefaultFormats ++ enumSerializers ++ DateSerializers.all implicit val serialization: org.json4s.Serialization = org.json4s.jackson.Serialization
调整导入语句:
import examples.openverse.core.JsonSupport.{jsonFormats, serialization}
内容的提问来源于stack exchange,提问作者griz
相关产品推荐
相关产品推荐

