使用Regex在Java中拆分嵌套JSON

时间:2022-01-06 21:46:00

I have a JSON string:

我有一个JSON字符串:

{name:"X",age:{dob:"DD MMM",year:YYYY}}

I need a Hashtable<String, String> pair like:

我需要一个Hashtable 对,如: ,string>

name: "X"
age: {dob:"DD MMM",year:YYYY}

I am currently using

我目前正在使用

string.substring(1,string.length() - 2).split(",");

How can I achieve this using regex?

如何使用正则表达式实现此目的?

3 个解决方案

#1


5  

Description

Providing your JSON text isn't nested beyond the level shown in your sample text, then this expression will:

提供您的JSON文本不会嵌套在示例文本中显示的级别之外,那么此表达式将:

  • capture the attribute name
  • 捕获属性名称

  • capture the attribute value
  • 捕获属性值

  • will keep arrays of values together and only return the top level
  • 将值数组保持在一起,只返回顶层

(?:,|\{)?([^:]*):("[^"]*"|\{[^}]*\}|[^},]*)

使用Regex在Java中拆分嵌套JSON

Example

Live Demo

Sample Text

{name:"X",age:{dob:"DD MMM",year:YYYY}}

Code

String sourcestring = "source string to match with pattern";
Pattern re = Pattern.compile("(?:,|\\{)?([^:]*):(\"[^\"]*\"|\\{[^}]*\\}|[^},]*)",Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
Matcher m = re.matcher(sourcestring);

Matches

[0][0] = {name:"X"
[0][1] = name
[0][2] = "X"

[1][0] = ,age:{dob:"DD MMM",year:YYYY}
[1][1] = age
[1][2] = {dob:"DD MMM",year:YYYY}

#2


3  

Here's how to do the whole lot in 4 lines:

以下是如何通过4行完成整个操作:

Map<String, String> map = new HashMap<String, String>();
String[] parts = json.replaceAll("^\\{|\\}$","").split("\"?(:|,)(?![^\\{]*\\})\"?");
for (int i = 0; i < parts.length -1; i+=2)
    map.put(parts[i], parts[i+1]);

This works as follows:

其工作原理如下:

  1. The head and tail braces are removed, because we can't easily split them out - they are junk
  2. 头部和尾部支撑被移除,因为我们不能轻易将它们分开 - 它们是垃圾

  3. The input is split by either a colon or a comma, optionally preceded/followed by a quote (this neatly consumes the quotes), but only if the next brace is not a close brace (meaning we're not in a nested term)
  4. 输入由冒号或逗号分隔,可选地在引号前面/后跟(这整齐地消耗引号),但仅当下一个括号不是紧括号时(意味着我们不在嵌套术语中)

  5. Loop by 2's over the split result putting pairs of name/value into the map
  6. 在分割结果上循环2,将名称/值对放入地图中

Here's some test code:

这是一些测试代码:

public static void main(String[] args) throws Exception {
    String json = "{name:\"X\",age:{dob:\"DD MMM\",year:YYYY}}";
    Map<String, String> map = new HashMap<String, String>();
    String[] parts = json.replaceAll("^\\{|\\}$","").split("\"?(:|,)(?![^\\{]*\\})\"?");
    for (int i = 0; i < parts.length -1; i+=2)
        map.put(parts[i], parts[i+1]);
    System.out.println(map.size() + " entries: " + map);
}

Output:

2 entries: {age={dob:"DD MMM",year:YYYY}, name=X}

#3


-3  

This would only be possible if recursrion was supported, which it unfortunately is not in java.

这只有在支持recursrion的情况下才有可能,遗憾的是它不在java中。

If recursrion was supported, this regex would do it: (?=({(?>[^{}]|(?1))+}))

如果支持recursrion,这个正则表达式会这样做:(?=({(?> [^ {}] |(?1))+}))

Live demo: http://regex101.com/r/pH7rV8

现场演示:http://regex101.com/r/pH7rV8

#1


5  

Description

Providing your JSON text isn't nested beyond the level shown in your sample text, then this expression will:

提供您的JSON文本不会嵌套在示例文本中显示的级别之外,那么此表达式将:

  • capture the attribute name
  • 捕获属性名称

  • capture the attribute value
  • 捕获属性值

  • will keep arrays of values together and only return the top level
  • 将值数组保持在一起,只返回顶层

(?:,|\{)?([^:]*):("[^"]*"|\{[^}]*\}|[^},]*)

使用Regex在Java中拆分嵌套JSON

Example

Live Demo

Sample Text

{name:"X",age:{dob:"DD MMM",year:YYYY}}

Code

String sourcestring = "source string to match with pattern";
Pattern re = Pattern.compile("(?:,|\\{)?([^:]*):(\"[^\"]*\"|\\{[^}]*\\}|[^},]*)",Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
Matcher m = re.matcher(sourcestring);

Matches

[0][0] = {name:"X"
[0][1] = name
[0][2] = "X"

[1][0] = ,age:{dob:"DD MMM",year:YYYY}
[1][1] = age
[1][2] = {dob:"DD MMM",year:YYYY}

#2


3  

Here's how to do the whole lot in 4 lines:

以下是如何通过4行完成整个操作:

Map<String, String> map = new HashMap<String, String>();
String[] parts = json.replaceAll("^\\{|\\}$","").split("\"?(:|,)(?![^\\{]*\\})\"?");
for (int i = 0; i < parts.length -1; i+=2)
    map.put(parts[i], parts[i+1]);

This works as follows:

其工作原理如下:

  1. The head and tail braces are removed, because we can't easily split them out - they are junk
  2. 头部和尾部支撑被移除,因为我们不能轻易将它们分开 - 它们是垃圾

  3. The input is split by either a colon or a comma, optionally preceded/followed by a quote (this neatly consumes the quotes), but only if the next brace is not a close brace (meaning we're not in a nested term)
  4. 输入由冒号或逗号分隔,可选地在引号前面/后跟(这整齐地消耗引号),但仅当下一个括号不是紧括号时(意味着我们不在嵌套术语中)

  5. Loop by 2's over the split result putting pairs of name/value into the map
  6. 在分割结果上循环2,将名称/值对放入地图中

Here's some test code:

这是一些测试代码:

public static void main(String[] args) throws Exception {
    String json = "{name:\"X\",age:{dob:\"DD MMM\",year:YYYY}}";
    Map<String, String> map = new HashMap<String, String>();
    String[] parts = json.replaceAll("^\\{|\\}$","").split("\"?(:|,)(?![^\\{]*\\})\"?");
    for (int i = 0; i < parts.length -1; i+=2)
        map.put(parts[i], parts[i+1]);
    System.out.println(map.size() + " entries: " + map);
}

Output:

2 entries: {age={dob:"DD MMM",year:YYYY}, name=X}

#3


-3  

This would only be possible if recursrion was supported, which it unfortunately is not in java.

这只有在支持recursrion的情况下才有可能,遗憾的是它不在java中。

If recursrion was supported, this regex would do it: (?=({(?>[^{}]|(?1))+}))

如果支持recursrion,这个正则表达式会这样做:(?=({(?> [^ {}] |(?1))+}))

Live demo: http://regex101.com/r/pH7rV8

现场演示:http://regex101.com/r/pH7rV8