【问题标题】:String replacing nested JSON in Scala在Scala中替换嵌套JSON的字符串
【发布时间】:2017-03-20 19:43:54
【问题描述】:

我有一个 Scala 方法,它会得到这样的字符串:

"blah blah sediejdri \"foos\": {\"fizz\": \"buzz\"}, odedrfj49 blah"

而且我需要使用纯 Java/Scala(无外部库)从中去除“foos JSON”。即找到匹配模式的子串:

\"foos\" : {ANYTHING},

...把它去掉,所以输入字符串现在是:

"blah blah sediejdri  odedrfj49 blah"

要搜索的令牌总是\"foos\",但 JSON 花括号内的内容总是不同的。我最好的尝试是:

// Ex:  "blah \"foos\": { flim flam }, blah blah"  ==>  "blah  blah blah", etc.
def stripFoosJson(var : toClean : String) : String = {
    val regex = ".*\"foos\" {.*},.*"
    toClean.replaceAll(regex, "")
}

但是我的正则表达式显然不正确。谁能发现我哪里出错了?

【问题讨论】:

  • 用正则表达式指定ANYTHING 并不容易,因为它可以包含也有大括号的嵌套对象...我会选择this answer,通过查找匹配的大括号并获取子字符串。
  • 谢谢@insan-e (+1) - 你说得对,但是在我的特殊情况下,我知道我不会在花括号内有任何嵌套的 JSON。

标签: regex scala


【解决方案1】:

这是我想出的 2 个解决方案,希望对您有所帮助。我想你忘了用\s* 等处理可能的空间。

object JsonStrip extends App {

    // SOLUTION 1, hard way, handles nested braces also:
    def findClosingParen(text: String, openPos: Int): Int = {
        var closePos = openPos
        var parensCounter = 1 // if (parensCounter == 0) it's a match!
        while (parensCounter > 0 && closePos < text.length - 1) {
            closePos += 1
            val c = text(closePos)
            if (c == '{') {
                parensCounter += 1
            } else if (c == '}') {
                parensCounter -= 1
            }
        }
        if (parensCounter == 0) closePos else openPos
    }

    val str = "blah blah sediejdri \"foos\": {\"fizz\": \"buzz\"}, odedrfj49 blah"
    val indexOfFoos = str.indexOf("\"foos\"")
    val indexOfFooOpenBrace = str.indexOf('{', indexOfFoos)
    val indexOfFooCloseBrace = findClosingParen(str, indexOfFooOpenBrace)
    // here you would handle if the brace IS found etc...
    val stripped = str.substring(0, indexOfFoos) + str.substring(indexOfFooCloseBrace + 2)
    println("WITH BRACE COUNT: " + stripped)

    // SOLUTION 2, with regex:
    val reg = "\"foos\"\\s*:\\s*\\{(.*)\\}\\s*,\\s*"
    println("WITH REGEX: " + str.replaceAll(reg, ""))
}

【讨论】:

  • 非常感谢 @insan-e (+1) - 解决方案 #2 非常适合我!
【解决方案2】:

This regex \\"foos\\": {(.*?)} 应该与您想要的匹配,在大多数正则表达式引擎中,您可能需要将" 替换为\"。如果您的 JSON 可以包含其他大括号,您可以使用 this \\"foos\\": \{(?&gt;[^()]|(?R))*\},它使用递归来匹配括号的平衡组。请注意,这个只适用于pcre正则表达式引擎,其他不支持递归。

【讨论】:

  • 感谢@Croutonix (+1) - 不,我不会在花括号内嵌套 JSON。但是,我不得不将您的正则表达式更改为\"foos\": {(.*?)},因为双反斜杠会导致 Scala 编译器错误。另外,你的第一个正则表达式给了我一个java.util.regex.PatternSyntaxException: Illegal repetition near index 7 "foos": {(.*?)} 异常......有什么想法吗?再次感谢!
  • here。您必须在花括号中添加反斜杠。 \"foos\": \{(.*?)\}
  • 嗯,你确定你让这些正则表达式对 Scala 是安全的吗?当我将正则表达式更改为"\"foos\": \{(.*?)\}" 时,我收到scalac 编译器错误,指出invalid escape character...再次感谢! (和 +1)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-11
  • 2021-10-24
  • 2013-01-19
  • 1970-01-01
  • 2020-09-02
  • 2014-04-09
  • 1970-01-01
相关资源
最近更新 更多