3

I have CLI app where user provide a JSON. I need to check if JSON is valid. I found somehting like this may work great:

function isJsonValid(str) {
    try {
        JSON.parse(str);
    } catch (e) {
        return false;
    }
    return true;
}

But while I debug my app i noticed that there is a little problem that all " and ' and spaces from command are stripped. so json as:

{
    "key1": "value1",
    "key2": "value2"
} 

is changed to something as:

{key1:value1,key2:value2}

I need a regex which will check if this stripped JSON is valid somehow.

So result should looks like:

re.test({key1:value1,key2:value2}) // true
re.test({key1:value1}) // true
re.test({key1:value1,}) // false, extra comma
re.test({key1:value1, key2}) // false, missing value of key2
re.test({key1:value1, key2:value2) // false, missing closing }
re.test({key1:value1, key2:value2}}) // false, extra closing }

Can someone please help me with regex part? This is unfortunately really not my strong side.

5
  • 2
    The "stripped" JSON is no longer JSON, but if that is your input and you want to validate it as is, do you just need to test the simple cases shown with only top-level key:value pairs, or do you have to allow for nested objects and/or arrays? Commented Sep 26, 2016 at 7:27
  • yep, there will bo no nested arrays. So I need to test if JSON looks like: { - opening bracket, key + : + value + closing bracket } While key:value part can repeat multiple time and should be seperate with comma Commented Sep 26, 2016 at 7:31
  • ??? Am I missing something important here? If your function returns true, the passed JSON is valid, if it returns false an error has occurred, and the JSON is not valid. Why to bother to re-check? Commented Sep 26, 2016 at 7:42
  • @Teemu - OP doesn't actually have JSON, the input is like JSON but without all the quotes. Commented Sep 26, 2016 at 7:44
  • I think you have to focus in the little problem you have with the JSON instead of evaluate the stripped version, There's definitely something wrong there.. Can you tell us how is that str variable passed to isJsonValid function? -- @Teemu, The function always return false because str is not JSON Commented Sep 26, 2016 at 7:46

2 Answers 2

4

Here you have the regex:

^{(([a-zA-Z0-9]+:[a-zA-Z0-9]+)(,[a-zA-Z0-9]+:[a-zA-Z0-9]+)*)?}$

Check your Examples here at Regex101.com

Sign up to request clarification or add additional context in comments.

2 Comments

thumb up, thank you for nice answer. I marked nnnn as correct because it's a bit more complex and he was first. However thank you a lot
I am glad I could help ! Marked or not marked, I'm glad you got the best solution possible.
3

As I mentioned in a comment above, the "stripped" JSON is of course no longer JSON at all. You have confirmed that you do not need to worry about nested objects or arrays, just a simple list of key:value pairs surrounded by curly brackets.

So, the following regex assumes that each key and value will be made up of "word" characters using the regex \w that is equivalent to [A-Za-z0-9_]:

var re = /^\{\w+:\w+(,\w+:\w+)*\}$/;

Obviously if you want to vary which characters are allowed as key names and values you can replace each \w with [A-Za-z0-9_] and just add or remove allowed characters as required.

EDIT: In a comment you mentioned allowing . in the key names and values. So using the case-insensitive i flag on the regex:

var re = /^\{[A-Z0-9._]+:[A-Z0-9._]+(,[A-Z0-9._]+:[A-Z0-9._]+)*\}$/i;

But you probably want to allow for optional white-space between all of the pieces, so I'd suggest adding \s* between all the tokens:

var re = /^\s*\{\s*[A-Z0-9._]+\s*:\s*[A-Z0-9._]+\s*(,\s*[A-Z0-9._]+\s*:\s*[A-Z0-9._]+\s*)*\}\s*$/i;

console.log( re.test('{key1:value1,key2:value2}') )   // true
console.log( re.test('{key1:value1}') )               // true
console.log( re.test(' { key1 : value1 , key2 : value2 ,  k3  :   v3  } ') ) // true
console.log( re.test(' { k.j.m : v.a2 , k2.a.b : v.32 ,  k3  :   v3  } ') ) // true
console.log( re.test('{key1:value1,}') )              // false, extra comma
console.log( re.test('{key1:value1, key2}') )         // false, missing value of key2
console.log( re.test('{key1:value1, key2:value2') )   // false, missing closing }
console.log( re.test('{key1:value1, key2:value2}}') ) // false, extra closing }

(Note that the bit I edited in to allow for . in the names will allow multiple . characters in a row, but I don't really want to keep coming back to update my answer as more requirements are added that weren't mentioned in the original post. If you want to keep it strictly one . in a row and no leading or trailing dots then just apply the same principle that the regex above used to make the commas work.)

2 Comments

Hey @nnnnnn can you consider value or key will be not just simple string but can be e.g. is.my.value (so added dots between)
Yes, I covered that in my answer: replace each \w with a list of the allowed characters in square brackets.

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.