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
(?:,|\{)?([^:]*):("[^"]*"|\{[^}]*\}|[^},]*)
Example
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:
- The head and tail braces are removed, because we can't easily split them out - they are junk
- 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)
- 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}
Author by
Samual krish
Updated on August 21, 2022Comments
-
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?