You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Scala Play解析JSON时如何对未知额外字段抛出错误

解决方案

Play JSON 提供的宏生成的 Reads 默认会忽略 JSON 中 case class 未定义的额外字段,不会抛出错误。要实现类似JSON Schema中additionalProperties: false的校验效果,可以通过自定义 Reads 增加字段校验逻辑实现,具体方案如下:


方案1:手动为指定case class编写带额外字段校验的Reads

核心思路是先校验JSON对象的所有键是否都在允许的字段列表中,校验通过后再执行常规的字段解析,示例代码如下:

import play.api.libs.json._

case class MyThing(fieldOne: Option[String])

object MyThing {
  // 定义允许的字段列表
  private val allowedFields = Set("fieldOne")
  
  implicit val reads: Reads[MyThing] = new Reads[MyThing] {
    override def reads(json: JsValue): JsResult[MyThing] = json match {
      case JsObject(fields) =>
        // 提取所有传入的字段名
        val inputFields = fields.keySet
        // 找出不在允许列表中的额外字段
        val extraFields = inputFields -- allowedFields
        if (extraFields.nonEmpty) {
          JsError(s"检测到未知字段:${extraFields.mkString(", ")}")
        } else {
          // 校验通过后用宏生成的Reads解析
          Json.reads[MyThing].reads(json)
        }
      case _ => JsError("期望输入为JSON对象")
    }
  }
}

该实现下,当传入包含fieldOne之外字段的JSON时,会直接返回JsError,符合校验需求。


方案2:封装通用校验逻辑(适用于多case class场景)

如果有大量case class需要做相同的额外字段校验,可以封装通用的校验方法,避免重复代码:

import play.api.libs.json._

object JsonValidationUtils {
  def withExtraFieldCheck[T](allowedFields: Set[String], underlying: Reads[T]): Reads[T] = new Reads[T] {
    override def reads(json: JsValue): JsResult[T] = json match {
      case JsObject(fields) =>
        val extraFields = fields.keySet -- allowedFields
        if (extraFields.nonEmpty) {
          JsError(s"未知字段:${extraFields.mkString(", ")}")
        } else {
          underlying.reads(json)
        }
      case _ => JsError("输入必须为JSON对象")
    }
  }
}

// 使用示例
case class MyThing(fieldOne: Option[String])
object MyThing {
  import JsonValidationUtils._
  implicit val reads: Reads[MyThing] = withExtraFieldCheck(
    allowedFields = Set("fieldOne"),
    underlying = Json.reads[MyThing]
  )
}

注意事项

  • 如果是嵌套的case class结构,需要为每一层的case class的Reads都加上额外字段校验,否则嵌套对象内的未知字段无法被检测到
  • 若需要兼容Play自带的错误格式规范,可以调整JsError的返回结构,和Play默认的字段错误格式对齐

内容的提问来源于stack exchange,提问作者James

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 16:45:07