如何在kotlin中编辑嵌套JSON
我有一个带有嵌套字段的JSON模型,它的开头是空的,我需要一点一点地添加/删除内容 以下是JSON结构及其默认值如何在kotlin中编辑嵌套JSON,json,kotlin,data-class,Json,Kotlin,Data Class,我有一个带有嵌套字段的JSON模型,它的开头是空的,我需要一点一点地添加/删除内容 以下是JSON结构及其默认值 { "id": "", "name": "", "age": 0, "address": { "streetName": "", "streetNumber": 0 } } 到目前为止,我尝试将JSON表示为String,并通过Kotlin数据类(使用Moshi或Gson库),但这两种方法都不允许我轻松更改嵌套属性 我想要的是一个函数,它执行以下
{
"id": "",
"name": "",
"age": 0,
"address": {
"streetName": "",
"streetNumber": 0
}
}
到目前为止,我尝试将JSON表示为String
,并通过Kotlin数据类
(使用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`
}
fun addToJson(key:String,value:T){
//在JSON中查找键(如果嵌套),可能表示指向该键的整个路径(即address.streetName)
//在其中插入值
//如果有一种方法可以“确定”字段的类型,这样我就不会冒险为“streetNumber”键设置一个“String”值,则可以获得额外的积分`
}
最终的目标是能够从应用程序中的任何地方调用类似于
addToJson(“path.to.key”,25)
的东西,其中的键可以表示为String
,也可以用任何其他简单的方式来表达
val jsonString = "{\n" +
" \"id\": \"\",\n" +
" \"name\": \"\",\n" +
" \"age\": 0,\n" +
" \"address\": {\n" +
" \"streetName\": \"\",\n" +
" \"streetNumber\": 0\n" +
" }\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)
这是你提出的一些问题
val jsonString = "{\n" +
" \"id\": \"\",\n" +
" \"name\": \"\",\n" +
" \"age\": 0,\n" +
" \"address\": {\n" +
" \"streetName\": \"\",\n" +
" \"streetNumber\": 0\n" +
" }\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数据绑定)库中的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\": 0\n" +
" }\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\": 0\n" +
" }\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)
尝试Jackson(Jackson数据绑定)库中的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\": 0\n" +
" }\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\": 0\n" +
" }\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)
您在Jackson库中尝试过ObjectNode吗?您在Jackson库中尝试过ObjectNode吗?谢谢,我不知道Jackson库中的ObjectNode。虽然我不确定它是否能达到预期的目标,也就是从代码中的任何地方可以执行类似于
addToJson(address.streetName,“Lenin”)
现在我明白了,您想要使用多级路径。我不知道有哪一个库支持这一点,但我为Jackson写了一篇小文章。啊,看起来确实不错:)我想不可能有一种方法“验证”路径,就好像它在类的n个实例的字段中一样。我会试着看看我能不能用这个,但我不认为验证是不可能的。您可以通过路径(字符串)到类型(类)的映射和类型检查来实现它-例如,检查setInJson调用“address:streetNumber”时,值是否为IntNode。另一种(更规范的)方法是json模式(使用这样的工具),但在每次修改之后使用它并不是最好的,只有在整个json形成之后。谢谢,我不知道Jackson库中的ObjectNode。虽然我不确定它是否能达到预期的目标,也就是从代码中的任何地方可以执行类似于addToJson(address.streetName,“Lenin”)
现在我明白了,您想要使用多级路径。我不知道有哪一个库支持这一点,但我为Jackson写了一篇小文章。啊,看起来确实不错:)我想不可能有一种方法“验证”路径,就好像它在类的n个实例的字段中一样。我会试着看看我能不能用这个,但我不认为验证是不可能的。您可以通过路径(字符串)到类型(类)的映射和类型检查来实现它-例如,检查setInJson调用“address:streetNumber”时,值是否为IntNode。另一种(更规范的)方法是json模式(使用这样的工具),但在每次修改之后使用它并不是最好的,只有在整个json形成之后,对于多次使用的同一个密钥,我希望能够找到一个可以在应用程序中随处使用的解决方案,或多或少类似于addToJson(address.streetName,“blala”)
So,对于多次使用的同一个密钥,我希望能够找到一个解决方案,该解决方案可以在应用程序中的任何地方使用,或多或少类似于addToJson(address.streetName,“blala”)