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

Scala中转换JsObject:如何处理可选字段?

问题分析与解决方案

你的代码主要存在三个核心问题:

  1. 类型不匹配:JsString/JsNumber的构造参数需要具体的String/Long类型,但你直接传入了Option[String]/Option[Long],编译会直接报错。
  2. 多余的Try块:asOpt方法本身就是安全的,字段不存在或类型错误时只会返回None,不会抛出异常,用Try包裹完全没必要。
  3. 类型转换错误:published是Long类型,应该用JsNumber而非JsString来构建对应JSON值。

下面提供两种修正方案:

方案一:手动处理可选字段转换

import play.api.libs.json._

val input = Json.obj(
  "title" -> "a book",
  "author" -> Json.obj("name" -> "mr smith"),
  "metadata" -> Json.obj("published" -> 10983920189403L)
)

case class Book(title: Option[String], author: Option[String], published: Option[Long])

def bookConvertor(inputObject: JsObject): JsObject = {
  // 安全获取所有可选字段
  val title = (inputObject \ "title").asOpt[String]
  val author = (inputObject \ "author" \ "name").asOpt[String]
  val published = (inputObject \ "metadata" \ "published").asOpt[Long]
  
  val book = Book(title, author, published)
  
  // 将存在的字段转换为JSON键值对,过滤掉None的字段
  val jsonFields = Seq(
    book.title.map("title" -> JsString(_)),
    book.author.map("author" -> JsString(_)),
    book.published.map("published" -> JsNumber(_))
  ).flatten
  
  JsObject(jsonFields)
}

说明

  • 用map对每个Option字段做转换:当字段存在时生成对应的JSON键值对,不存在时返回None。
  • flatten会过滤掉所有None元素,最终输出的JsObject只包含输入中实际存在的字段。如果需要把不存在的字段保留为null,可以把map改成fold:
    "title" -> book.title.fold(JsNull)(JsString(_))
    

方案二:使用Play JSON自动格式化(推荐)

Play JSON支持通过宏自动生成类型的序列化/反序列化规则,代码更简洁且不易出错:

import play.api.libs.json._

val input = Json.obj(
  "title" -> "a book",
  "author" -> Json.obj("name" -> "mr smith"),
  "metadata" -> Json.obj("published" -> 10983920189403L)
)

case class Book(title: Option[String], author: Option[String], published: Option[Long])

// 自动生成Book的JSON格式化器
implicit val bookFormat: OFormat[Book] = Json.format[Book]

def bookConvertor(inputObject: JsObject): JsObject = {
  // 安全解析输入JSON为Book实例,再序列化为目标JSON
  inputObject.validate[Book].fold(
    _ => JsObject(Seq.empty), // 解析失败时返回空对象,可根据需求调整
    book => Json.toJson(book).as[JsObject]
  )
}

说明

  • Json.format[Book]宏会根据case class的结构自动生成解析和序列化逻辑,自动处理可选字段的空值情况。
  • validate方法返回JsResult[Book],通过fold分别处理解析成功和失败的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 06:03:24