You need to enable JavaScript to run this app. 如何高效为嵌套JsonObject动态新增以自身stat值为名、data值为值的字段
优惠活动
大模型
产品
解决方案
定价
更多

如何高效为嵌套JsonObject动态新增以自身stat值为名、data值为值的字段

修正后的Gson实现(无额外依赖,适配现有代码)

该方案直接在原JSON对象上修改,不新建冗余结构,完全保留原有字段和数据类型,无重复解析操作。

import com.google.gson.{JsonArray, JsonObject, JsonParser, JsonPrimitive}

// 替换为你的实际输入JSON字符串
val inputJsonStr = """{"values":[{"id":"1","properties":[{"stat":"memory","data":8},{"stat":"cpu","data":4}]},{"id":"2","properties":[{"stat":"status","data":"OK"},{"stat":"cpu","data":4}]}]}"""
val rootObject = JsonParser.parseString(inputJsonStr).getAsJsonObject

// 遍历values数组
val valuesArray = rootObject.getAsJsonArray("values")
valuesArray.forEach { valueElem =>
  val valueObj = valueElem.getAsJsonObject
  // 仅处理存在properties字段的对象
  if (valueObj.has("properties")) {
    val propsArray = valueObj.getAsJsonArray("properties")
    // 逐个处理properties内的对象
    propsArray.forEach { propElem =>
      val propObj = propElem.getAsJsonObject
      // 仅同时存在stat、data字段时执行新增
      if (propObj.has("stat") && propObj.has("data")) {
        val newFieldKey = propObj.get("stat").getAsString
        /* 若需要实现你期望输出中非数字类型data设为0的逻辑,使用下面的newFieldValue定义
        val newFieldValue = propObj.get("data") match {
          case num if num.isJsonNumber => num
          case _ => JsonPrimitive(0)
        }
        */
        // 保留原始data类型的写法
        val newFieldValue = propObj.get("data")
        propObj.add(newFieldKey, newFieldValue)
      }
    }
  }
}

// 输出处理后的JSON
val outputJsonStr = rootObject.toString
函数式实现(circe库,类型安全)

如果使用Scala生态常用的circe库,代码更简洁,错误处理更完善:

import io.circe.{Json, JsonObject}
import io.circe.parser._
import io.circe.syntax._

val inputJsonStr = """{"values":[{"id":"1","properties":[{"stat":"memory","data":8},{"stat":"cpu","data":4}]},{"id":"2","properties":[{"stat":"status","data":"OK"},{"stat":"cpu","data":4}]}]}"""

val processResult = for {
  rootJson <- parse(inputJsonStr)
  rootObj <- rootJson.asObject.toRight("根节点不是JSON对象")
  valuesArray <- rootObj("values").flatMap(_.asArray).toRight("values字段不是数组")
  // 处理每个value元素
  updatedValues = valuesArray.map { valueJson =>
    val valueObj = valueJson.asObject.getOrElse(JsonObject.empty)
    val propsArray = valueObj("properties").flatMap(_.asArray).getOrElse(Seq.empty)
    // 处理每个properties元素
    val updatedProps = propsArray.map { propJson =>
      val propObj = propJson.asObject.getOrElse(JsonObject.empty)
      val statKey = propObj("stat").flatMap(_.asString).getOrElse("")
      // 非数字类型默认设为0,需要保留原类型可替换为val dataVal = propObj("data").getOrElse(Json.Null)
      val dataVal = propObj("data").filter(_.isNumber).getOrElse(Json.fromInt(0))
      propObj.add(statKey, dataVal).asJson
    }
    valueObj.add("properties", updatedProps.asJson).asJson
  }
  // 替换根节点的values字段
  updatedRoot = rootObj.add("values", updatedValues.asJson)
} yield updatedRoot.asJson.noSpaces

// 输出结果,处理失败时返回错误信息
val output = processResult.fold(
  error => s"JSON处理失败: $error",
  success => success
)
方案优势
  • 仅单次解析JSON,无重复读取、手动字符串拼接操作
  • 按层级遍历结构,避免原有JsonPath实现的通配符匹配导致的跨元素错配问题
  • 直接在原对象上新增字段,完全保留原有stat、data等字段,不修改原有内容
  • 对缺失字段的场景有容错,不会抛出空指针异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.26 23:06:04