如何使用Scala Circe批量修改指定键名的所有JSON字段值?
使用Scala Circe批量修改指定键名的字段值
核心思路
Circe的findAllByKey仅支持查询匹配键的值,无法直接修改JSON结构。要实现递归修改所有指定键(比如validTo)的字段值,我们可以基于Circe的JSON遍历能力,自定义递归处理函数,遍历所有节点并替换目标字段。
具体实现
1. 日期偏移工具方法
先实现一个处理日期字符串的函数,负责将validTo的日期值偏移指定天数:
import java.time.{OffsetDateTime, Period} import java.time.format.DateTimeFormatter def offsetValidToDate(dateStr: String, days: Int): String = { val formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME val originalDate = OffsetDateTime.parse(dateStr, formatter) val newDate = originalDate.plus(Period.ofDays(days)) formatter.format(newDate) }
2. 递归修改JSON的自定义函数
编写递归遍历逻辑,处理JSON的所有节点,遇到目标键就替换其值:
import io.circe.{Json, JsonObject} def modifyAllByKey(json: Json, targetKey: String, modifyFn: String => String): Json = { json.fold( Json.Null, bool => Json.fromBoolean(bool), num => Json.fromJsonNumber(num), str => Json.fromString(str), arr => Json.fromValues(arr.map(modifyAllByKey(_, targetKey, modifyFn))), obj => { val modifiedEntries = obj.toList.map { case (`targetKey`, Json.fromString(value)) => targetKey -> Json.fromString(modifyFn(value)) case (key, value) => key -> modifyAllByKey(value, targetKey, modifyFn) } Json.fromJsonObject(JsonObject.fromIterable(modifiedEntries)) } ) }
3. 调用示例
结合上述方法处理目标JSON:
// 示例输入JSON val inputJson = Json.obj( "user" -> Json.obj( "validTo" -> Json.fromString("2024-09-12T00:00:00.000+00:00"), "profile" -> Json.obj( "subscription" -> Json.obj( "validTo" -> Json.fromString("2024-10-01T00:00:00.000+00:00") ) ) ), "products" -> Json.arr( Json.obj("id" -> Json.fromInt(1), "validTo" -> Json.fromString("2024-11-05T00:00:00.000+00:00")), Json.obj("id" -> Json.fromInt(2)) ) ) // 将所有validTo日期偏移30天 val modifiedJson = modifyAllByKey(inputJson, "validTo", offsetValidToDate(_, 30)) println(modifiedJson.spaces2)
关键说明
- 该方法会递归遍历JSON的所有嵌套节点,无论
validTo处于多深的层级都能被匹配修改。 - 示例针对
validTo为字符串类型的场景处理,若你的JSON中该字段是其他类型(如时间戳数字),可扩展对象处理分支的逻辑。
内容的提问来源于stack exchange,提问作者sentenza
相关产品推荐
相关产品推荐

