如何在kotlin中编辑嵌套的JSON



我有一个带有嵌套字段的JSON模型,该字段以空开头,我需要一点一点地添加/删除内容。

以下是JSON结构及其默认值

{
"id": "",
"name": "",
"age": 0,
"address": {
"streetName": "",
"streetNumber": 0
}
}

到目前为止,我尝试了将JSON表示为String和通过Kotlindata class(使用Moshi或Gson库(,但这两种方法都不允许我轻松更改嵌套属性。

我想要的是一个执行以下的功能

fun <T>addToJson(key: String, value: T) {
// Finds the key in the JSON, if nested, maybe expressing the whole path to it (i.e. address.streetName)
// Inserts the value in it
// Bonus points if there was a way to 'determine' the type of the field so that I don't risk to set for the key `streetNumber` a value that is `String`
}

最终目标是能够从应用程序中的任何地方调用类似addToJson("path.to.key", 25)的东西,密钥要么表示为String,要么以任何其他简单的方式

这将您的提问视为一些问题。

  1. 如果使用同一个嵌套键的次数超过一次
  2. T值必须是已知的JSON对象类型基元数组或JSON对象,您计划如何在运行时强制执行这一点

这里有一个关于如何访问对象中的每个属性的示例

val jsonString = "{n" +
"  "id": "",n" +
"  "name": "",n" +
"  "age": 0,n" +
"  "address": {n" +
"    "streetName": "",n" +
"    "streetNumber": 0n" +
"  }n" +
"}"
val gson = Gson()
val jsonElement = gson.fromJson(jsonString, JsonElement::class.java).asJsonObject
jsonElement.addProperty("id",26)
jsonElement.addProperty("name","sof")
jsonElement.addProperty("age",33)
val nested = jsonElement.get("address").asJsonObject
nested.addProperty("streetName","blala")
nested.addProperty("streetNumber",12)
print(jsonElement)

在Jackson(Jackson databind(库中尝试ObjectNode

你可以从头开始构建

val factory = JsonNodeFactory(true)
val o = ObjectNode(factory)
o.set("id", IntNode(15))
o.set("name", TextNode("yourname"))
o.set("lastName", TextNode("lastname"))
val address = ObjectNode(factory)
o.set("address", address)
address.set("streetName", TextNode("Lenin"))
address.set("streetNumber", IntNode(5))
address.set("buildingNumber", IntNode(15))
println(o)

或者加载现有的json并修改它

val json = "{n" +
"  "id": "",n" +
"  "name": "",n" +
"  "age": 0,n" +
"  "address": {n" +
"    "streetName": "",n" +
"    "streetNumber": 0n" +
"  }n" +
"}"
val o : ObjectNode = (ObjectMapper()).readTree(json) as ObjectNode
o.set("id", IntNode(15))
o.set("name", TextNode("yourname"))
val address = o.get("address") as ObjectNode
address.set("streetName", TextNode("Lenin"))
address.set("streetNumber", IntNode(5))
address.set("buildingNumber", IntNode(15))
println(o)

我不知道Json中有哪个库支持多级路径。但实现这样的东西相当容易:

fun setInJson(root: ObjectNode, objectMapper: ObjectMapper, path: String, value: JsonNode) {
val splitPath = path.split(":")
val lastName = splitPath.last()
val notLastNames = splitPath.subList(0, splitPath.size - 1)
var node = root
notLastNames.forEach { nodeName ->
node = (node.get(nodeName) as ObjectNode?) ?: {
val newNode = objectMapper.createObjectNode()
node.set(nodeName, newNode)
newNode
}()
}
node.set(lastName, value)
}

可用作:

val json = "{n" +
"  "id": "",n" +
"  "name": "",n" +
"  "age": 0,n" +
"  "address": {n" +
"    "streetName": "",n" +
"    "streetNumber": 0n" +
"  }n" +
"}"
val om = ObjectMapper()
val o : ObjectNode = (ObjectMapper()).readTree(json) as ObjectNode
setInJson(o, om, "id", IntNode(15))
setInJson(o, om, "name", TextNode("yourname"))
setInJson(o, om, "address:streetName", TextNode("Lenin"))
setInJson(o, om, "address:streetNumber", IntNode(5))
println(o)

最新更新