如何通过Circe修改JSON字段类型?优化字符串转整数实现
优化Circe修改JSON字段类型的实现
你的这段代码确实有点繁琐,而且jsObj.asObject.get这种调用是不安全的——万一JSON解析失败或者没有test字段,直接就会抛出异常。我来给你两种优化思路,一种是用Circe原生的更安全的API,另一种是用Circe Optics来简化操作,后者特别适合这种精准修改JSON某个路径值的场景。
一、Circe原生API的安全优化
我们可以利用Circe的HCursor来安全地定位字段、转换值,同时处理可能的异常情况(比如字段不存在、字符串无法转整数):
首先导入必要的包:
import io.circe._ import io.circe.parser._
然后实现代码:
val str = """{"test":"123"}""" // 安全处理解析和转换的全流程 val result: Either[Error, Json] = for { // 解析原始JSON,返回Either处理失败情况 originalJson <- parse(str) // 获取test字段的字符串值,失败则进入Left分支 testStr <- originalJson.hcursor.get[String]("test") // 尝试将字符串转整数,处理转换失败的情况 testInt <- Either.catchNonFatal(testStr.toInt).leftMap(e => ParsingFailure(s"Failed to parse integer: ${e.getMessage}", e)) // 修改JSON字段值 updatedJson <- originalJson.hcursor .downField("test") .withFocus(_ => Json.fromInt(testInt)) .top .toRight(new Error("Failed to update JSON structure")) } yield updatedJson
这个版本全程用Either处理所有可能的失败场景,避免了不安全的.get调用,代码也更清晰。
二、Circe Optics的简洁实现
Circe Optics专门用于JSON的“聚焦式”操作,能让你像操作普通数据结构一样精准修改JSON的某个路径,代码会非常简洁。
首先需要导入Optics的包(确保你的依赖里包含了circe-optics):
import io.circe._ import io.circe.parser._ import io.circe.optics.JsonPath._
然后实现代码:
val str = """{"test":"123"}""" // 定义指向`test`字符串字段的Optic val testStringField = root.test.string // 安全处理的版本:解析后修改,同时处理转换异常 val result: Either[Error, Json] = parse(str).flatMap { json => testStringField.modifyF { s => Either.catchNonFatal(Json.fromInt(s.toInt)).leftMap(e => ParsingFailure(s"Invalid integer: $s", e)) }(json) } // 如果不需要严格处理异常(仅做示例),可以更简洁: val simpleUpdatedJson = testStringField.modify(_.toInt)(parse(str).getOrElse(Json.Null))
Optics的好处在于:
- 不需要手动操作
JsonObject的remove/add,直接针对目标路径修改 - 代码可读性极高,一眼就能看出是在修改
root.test这个字段 - 可以通过
modifyF、modifyOption等方法灵活处理异常或不存在的字段
比如用modifyOption处理转换失败的情况:
val safeUpdatedJson: Option[Json] = parse(str).toOption.flatMap { json => testStringField.modifyOption(s => Either.catchNonFatal(Json.fromInt(s.toInt)).toOption)(json) }
如果test字段不是字符串,或者字符串无法转整数,这个方法会返回None,避免抛出异常。
内容的提问来源于stack exchange,提问作者Oleg
相关产品推荐
相关产品推荐

