2016-11-07 62 views
1

替换嵌套JSON我有一个Scala的方法,该方法将给出一个字符串,象这样:字符串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, "") 
} 

但是,我的正则表达式显然不正确。任何人都可以发现我要去哪里?

+1

这是不容易指定'ANYTHING'用正则表达式,因为它可以包含有括号也嵌套的对象......我会用[此去答案](http://stackoverflow.com/questions/12752225/how-do-i-find-the-position-of-matching-parentheses-or-braces-in-a-given-piece-of),找到匹配大括号和子字符串。 –

+0

Thanks @ insan-e(+1) - 你是对的,但是在我的特殊情况下,我*知道*我将不会在花括号内嵌入任何嵌套的JSON。 – smeeb

回答

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, "")) 
} 
+0

非常感谢@ insan-e(+1) - 解决方案#2对我来说非常完美! – smeeb

+0

不客气!很高兴帮助。 :) –

2

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

+0

谢谢@Croutonix(+1) - 不,我不会在花括号内部嵌套JSON。然而,我不得不改变你的正则表达式为'\“foos \”:{(。*?)}',因为双反斜杠导致Scala编译器错误。另外,你的第一个正则表达式给了我一个java.util.regex.PatternSyntaxException:在索引7“foos”附近有非法重复:{(。*?)}异常......任何想法?再次感谢! – smeeb

+1

请参阅[这里](http://stackoverflow.com/a/8751574/5288316)。你必须添加一个反斜杠来大括号。 '\“foos \”:\ {(。*?)\}' –

+0

嗯,你确定你正在为Scala安全使用这些正则表达式吗?当我将正则表达式更改为'“\”foos \“:\ {(。*?)\}”时,我得到'scalac'编译器错误,指出'无效转义字符'...但是再次感谢! (和+1) – smeeb