以递归方式从Groovy中的JSON字段名称中删除空格

时间:2016-10-11 08:43:41

标签: json regex groovy

我有一个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"}

有点/有点接近,但不完全是我需要的。有什么想法吗?

1 个答案:

答案 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",并且将保留原始内容。