我有一个Groovy进程正在接收麻烦的JSON,其中包含包含空格的属性/字段名称:
{
"leg bone" : false,
"connected to the" : {
"arm bones " : [
{
" fizz" : "buzz",
"well hello" : "there"
}
]
}
}
上面,"leg bone"
和"well hello"
等字段在处理过程中会导致问题(即使它们在技术上是合法的JSON字段)。所以我想在传入的JSON和字符串中扫描每个字段(递归或嵌套),用下划线替换任何空格(" _")。因此,上述JSON将转换为:
{
"leg_bone" : false,
"connected_to__the" : {
"arm_bones_" : [
{
"_fizz" : "buzz",
"well_hello" : "there"
}
]
}
}
通常我使用JsonSlurper
将JSON字符串解析为映射,但我似乎无法弄清楚如何使递归正确。到目前为止,这是我最好的尝试:
// In reality 'incomingJson' isn't hardcoded as a string literal, but this helps make my actual use case
// an SSCCE.
class JsonMapExperiments {
static void main(String[] args) {
String incomingJson = """
{
"leg bone" : false,
"connected to the" : {
"arm bones " : [
{
" fizz" : "buzz",
"well hello" : "there"
}
]
}
}
"""
String fixedJson = fixWhitespaces(new JsonSlurper().parseText(incomingJson))
println fixedJson
}
static String fixWhitespaces(def jsonMap) {
def fixedMap = [:]
String regex = ""
jsonMap.each { key, value ->
String fixedKey = key.replaceAll('\\s+', '_')
String fixedValue
if(value in Map) {
fixedValue = fixWhitespaces(value)
} else {
fixedValue = value
}
fixedMap[fixedKey] = fixedValue
}
new JsonBuilder(fixedMap).toString()
}
}
运行时,最终输出为:
{"connected_to_the":"{\"arm_bones_\":\"[{ fizz=buzz, well hello=there}]\"}","leg_bone":"false"}
有点/有点接近,但不完全是我需要的。有什么想法吗?
答案 0 :(得分:1)
鉴于您的输入和此脚本:
def fixWhitespacesInTree(def tree) {
switch (tree) {
case Map:
return tree.collectEntries { k, v ->
[(k.replaceAll('\\s+', '_')):fixWhitespacesInTree(v)]
}
case Collection:
return tree.collect { e -> fixWhitespacesInTree(e) }
default :
return tree
}
}
def fixWhitespacesInJson(def jsonString) {
def tree = new JsonSlurper().parseText(jsonString)
def fixedTree = fixWhitespacesInTree(tree)
new JsonBuilder(fixedTree).toString()
}
println fixWhitespacesInJson(json)
我得到了以下结果:
{"connected_to_the":{"arm_bones_":[{"_fizz":"buzz","well_hello":"there"}]},"leg_bone":false}
但是,我建议您将正则表达式\\s+
更改为\\s
。在前一种情况下。如果您在同一级别有两个JSON属性,一个名为" fizz"
,另一个名为" fizz"
,则翻译的密钥将为"_fizz"
,一个将覆盖最终结果中的另一个。在后一种情况下,翻译的密钥将分别为"_fizz"
和"__fizz"
,并且将保留原始内容。