Split Nested JSON in Java with Regex

10,471

Solution 1

Description

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

  • capture the attribute name
  • capture the attribute value
  • will keep arrays of values together and only return the top level

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

enter image description here

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}

Solution 2

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

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. 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)
  3. Loop by 2's over the split result putting pairs of name/value into the map

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}
Share:
10,471
Samual krish
Author by

Samual krish

Updated on August 21, 2022

Comments

  • Samual krish
    Samual krish over 1 year

    I have a JSON string:

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

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

    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?