4

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?

6
  • 3
    Using regex for parsing json is bad pretty much always. I suggest that you use a JSON parsing library instead. Commented Jul 27, 2013 at 22:58
  • 1
    Using regex to parse JSON instead of a propper library is like having my soup with a hammer instead of a spoon, just not the correct tool. Commented Jul 27, 2013 at 23:00
  • I agree that parsing JSON without a library is a tedious task. But is there a logic which could be implemented. Commented Jul 27, 2013 at 23:06
  • You would need a recursive method. Just parse everything then check each bit so see if there is more JSON. If there is then call the same method again... Commented Jul 27, 2013 at 23:09
  • @BoristheSpider Could you provide a sample example Commented Jul 27, 2013 at 23:14

3 Answers 3

6

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}
Sign up to request clarification or add additional context in comments.

Comments

3

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}

3 Comments

Wow!! This looks much simpler
Hi @Bohemian Could you kindly explain the regex function. I am new to regex hard to decyrpt.
No worries - I can explain, but what part exactly? Do you want a detailed breakdown of the regex? BTW you can (if you wish) "unaccept" an already-accepted answer then accept mine ;-)
-3

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

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

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

5 Comments

But like you said, that won't work in Java, so why mention it? If he dropped his car keys in the middle of the block, would you tell him to look for them at the intersection because the light's better there? ;)
@AlanMoore: he wanted a regex solution, i gave him one. I figured it was worth mentioning if he was going to switch language and just as general information.
@Lindrian, I think Alan's point was that you knowingly provided a solution which doesn't work. Which is not exactly the purpose of a question and answer site.
@Denomales: Because there is no complete regex answer to his question, besides mine. Regardless, this does not seem to be appreciated, so I will not do it again in the future.
@Lindrian I agree there is no complete solution to matching JSON text with a regex, however the accepted solution here is a regex which will parse the OP's sample JSON text using Java's regular expression engine.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.