4

我有一个 JSON 字符串:

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

我需要一Hashtable<String, String>对像:

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

我目前正在使用

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

如何使用正则表达式实现这一点?

4

3 回答 3

6

描述

如果您的 JSON 文本没有嵌套超出示例文本中显示的级别,则此表达式将:

  • 捕获属性名称
  • 捕获属性值
  • 将值数组保持在一起,只返回顶层

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

在此处输入图像描述

例子

现场演示

示例文本

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

代码

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

火柴

[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}
于 2013-07-28T03:31:02.183 回答
3

以下是如何在 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]);

这工作如下:

  1. 头部和尾部的支架被移除,因为我们不能轻易地将它们分开——它们是垃圾
  2. 输入由冒号或逗号分隔,可选地在引号之前/之后(这巧妙地消耗了引号),但前提是下一个大括号不是右大括号(意味着我们不在嵌套术语中)
  3. 在拆分结果上循环 2,将名称/值对放入映射中

下面是一些测试代码:

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);
}

输出:

2 entries: {age={dob:"DD MMM",year:YYYY}, name=X}
于 2013-07-28T04:37:37.750 回答
-3

这只有在支持递归的情况下才有可能,不幸的是它不在 java 中。

如果支持递归,则此正则表达式将执行此操作:(?=({(?>[^{}]|(?1))+}))

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

于 2013-07-27T23:28:49.657 回答