gson 遍历嵌套的JsonObject

cgvd09ve  于 2022-11-06  发布在  其他
关注(0)|答案(1)|浏览(222)

我在我的应用程序中使用Gson来解析JSON。我有一个特殊的用例,我想获取一个JsonObject并有效地对其进行深度克隆,除了改变匹配某些特定条件的键/值。
例如,假设源对象如下所示:

{
  "foo": {
    "bar": {
      "baz": "some value here"
    },
    "baz": "another value here"
  }
}

我想遍历每个键(不管它是如何嵌套的),如果有一个名为baz的键,我将运行我的转换函数,我的输出对象将如下所示:

{
  "foo": {
    "bar": {
      "bazTransformed": "this got altered by my function"
    },
    "bazTransformed": "so did this"
  }
}

我知道我可以做一些事情,比如将JsonObject转换为字符串,然后使用RegEx模式来查找和替换,但这感觉不对。
我真的很难让我的头周围创建一个递归函数,或至少一个比字符串操纵更好的解决方案。
我可以从JsonObject.entrySet()开始迭代,但这会返回一个Map〈String,JsonElement〉--这似乎增加了更多的复杂性,因为在继续递归之前,我需要首先检查JsonElement是否是一个JsonObject。
编辑:在我看来,最好将JsonObject转换为Map,如下所示:gson.fromJson(sourceObj, Map::class.java) as MutableMap<*, *>
我可以写一个递归迭代的函数,如下所示:

fun generateObject(sourceObj: JsonElement): JsonObject {
    val inputMap = gson.fromJson(sourceObj, Map::class.java) as MutableMap<*, *>

    val outputMap: MutableMap<String, Any> = mutableMapOf()

    fun go(toReturn: MutableMap<String,Any>,
           input: MutableMap<String, Any>) {
            for ((key, value) in input) {
                if (key == "baz") {
                    println("baz key found")
                    //do my transformation here

                }
                if (value is Map<*, *>) {
                    println("nested map")
                    go(toReturn, value as MutableMap<String, Any>)
                }
                // this part is wrong however, because `key` is potentially nested
                outputMap[key] = value
            }

    }

    go(outputMap, inputMap as MutableMap<String, Any>)

    return gson.toJsonTree(outputMap).asJsonObject
}
wrrgggsh

wrrgggsh1#

多亏了一个朋友的帮助,我找到了这个问题的答案。希望这能帮助将来遇到同样问题的其他人。

val inputMap = mapOf(
      "foo" to mapOf(
          "bar" to mapOf(
              "baz" to "something composable")))

  val expectedOutputMap = mutableMapOf(
      "foo" to mutableMapOf(
          "bar" to mutableMapOf(
              "bux" to "here be some data")))

    fun go(input: Map<String, Any>) : Map<String, Any> {
      return input.entries.associate {
        if (it.key == "baz") {
          // alternatively, call some transformation function here
            "bux" to "here be some data"
        } else if ( it.value is Map<*, *>) {
            it.key to go(it.value as Map<String, Any>)
        } else {
            it.key to it.value                        
        }

      }
    }

    val outputMap = go(inputMap)

我的用例最终的发展略有不同。对于我的用例,我需要实际获取一个JsonObject,遍历它,如果我找到了一个特定的键,那么我将读取该键的内容,并构建一个新的JsonElement来代替它。
我在这里提供的解决方案忽略了这一细节,因为这有点绕路,但是您可以看到这种转换将在哪里发生。

相关问题