Scala Play中如何为两个控制器端点切换隐式JSON格式化器
Scala Play 多版本JSON格式化器切换问题
问题描述
现有基于Scala Play框架开发的接口,返回嵌套结构的复杂JSON配置,配置层级如下:
Configuration |__ DBConfig |__ SecretDef |__ SecondDBConfig |__ SecretDef |__ AuthConfig |__ SecretDef
序列化该配置共使用20余个隐式格式化器,其中敏感字段类型SecretDef的默认格式化器直接返回原值,实现如下:
implicit val fSecretFormat: Format[SecretDef] = new Format[SecretDef] { override def writes(o: SecretDef): JsValue = Json.toJson(o.value) override def reads(json: JsValue): JsResult[SecretDef] = ??? }
现需要开发该接口的V2版本,返回完整配置结构,但SecretDef字段的序列化逻辑需替换为AES解密后的值,对应格式化器实现如下:
implicit val fSecretFormatDec: Format[SecretDef] = new Format[SecretDef] { override def writes(o: SecretDef): JsValue = Json.toJson(decryptWithAES(o.value)) override def reads(json: JsValue): JsResult[SecretDef] = ??? }
实际开发中遇到问题:控制器已全局导入所有隐式格式化器,无法在V2端点的单独Action中完成SecretDef隐式格式化器的切换。曾尝试在Action作用域内定义优先级更高的隐式值,写法如下,但未生效:
Action.async { implicit request => implicit val fSecret: Format[SecretDef] = utils.SecretFormatters.fSecretFormatEnc for { config <- configRepo.getConfig() } yield Ok(Json.toJson(tenant)) }
解决方案
参考Gaël J的建议,通过抽象格式化器特质、拆分不同版本实现的方式解决,代码如下:
trait Formatters { implicit def getSecretDef: Format[SecretDef] // 其余所有依赖SecretDef的隐式格式化器均在此处定义为def } // V1版本格式化器:返回SecretDef原值 object JsonFormatters extends Formatters { override implicit def getSecretDef: Format[SecretDef] = SecretFormatters.fSecretFormat } // V2版本格式化器:返回SecretDef解密后的值 object JsonFormattersV2 extends Formatters { override implicit def getSecretDef: Format[SecretDef] = SecretFormatters.fSecretFormatDec }
使用时无需全局导入格式化器,仅需在对应版本接口的Action作用域内导入对应版本的格式化器对象,即可自动完成序列化逻辑的切换。
内容的提问来源于stack exchange,提问作者zoran jeremic
相关产品推荐
相关产品推荐

