Scala含关键字`type`的case类模式匹配与Circe适配问题
解决Circe case类含关键字字段的模式匹配问题
遇到Scala关键字作为JSON字段名的情况,不用修改源JSON schema,有几种实用解决办法:
方法1:模式匹配时给关键字字段加反引号
既然case类里的字段是用type(反引号包裹)定义的,模式匹配里引用该字段时同样加反引号,让编译器识别这是字段名而非关键字:
case class Event(`type`: String, id: String) // 模式匹配示例 event match { case Event(`type` = eventType, eventId) => // 用eventType和eventId处理写入逻辑 db.insert(eventType, eventId) case _ => // 处理其他情况 }
也可以直接提取字段并起别名,不用显式写字段名(字段较多时显式标注更清晰):
event match { case Event(t, id) => // t就是`type`字段的值,直接使用 db.insert(t, id) }
方法2:给case类字段映射JSON别名(更推荐)
如果不想反复处理反引号,可以给case类字段起非关键字名称,通过Circe注解映射到JSON的type字段,需要用到Circe的generic-extras模块:
import io.circe.generic.extras.JsonKey import io.circe.generic.extras.semiauto._ // 用eventType作为case类字段名,通过注解映射到JSON的type字段 case class Event(@JsonKey("type") eventType: String, id: String) // 生成对应的编解码器 implicit val eventCodec = deriveConfiguredCodec[Event]
这样解析JSON时,type字段会自动映射到eventType,模式匹配直接用eventType即可,完全避开关键字冲突:
event match { case Event("click", id) => db.insert("click", id) case Event("view", id) => db.insert("view", id) }
方法3:匹配后通过对象访问字段
如果不想改动模式匹配写法,也可以先匹配整个对象,再通过反引号访问字段:
event match { case e => val eventType = e.`type` db.insert(eventType, e.id) }
内容的提问来源于stack exchange,提问作者Vishakh
相关产品推荐
相关产品推荐

