Want to improve this question? As written, this question is lacking some of the information it needs to be answered. If the author adds details in comments, consider editing them into the question. Once there's sufficient detail to answer, vote to reopen the question.
Closed 3 years ago.
Write a program that determines whether its input is valid JSON.
Input: ASCII text: [\x00-\x7F]*
Note: if ASCII is problematic, feel free to use another encoding, but indicate it in your post.
Output: Valid
or Invalid
. Trailing newline may be omitted.
Example:
$ echo '{"key": "value"}' | ./json-validate
Valid
$ echo '{key: "value"}' | ./json-validate
Invalid
Rules:
The shortest correct solution wins.
Please run json-validate-test-suite.sh on your program, and post your score. Example:
$ ./json-validate-test-suite.sh ./buggy-prog
fail: should be invalid: [ 0.1e ]
fail: should be invalid: [ 0.1e+-1 ]
fail: should be invalid: [ 0.1e-+1 ]
score: 297/300
Resources:
The JSON grammar is as follows:
json: object | array
object: '{' members? '}'
members: pair (',' pair)*
pair: string ':' value
array: '[' elements? ']'
elements: value (',' value)*
value: string
| number
| object
| array
| 'true'
| 'false'
| 'null'
string: '"' char* '"'
char: [^"\\\x00-\x1F]
| '\' escape
escape: ["\\/bfnrt]
| u [0-9A-Fa-f]{4}
number: '-'? (0 | [1-9][0-9]*) ('.' [0-9]+)? ([Ee] [+-]? [0-9]+)?
Also, whitespace can appear before or after any of the six structural characters {}[]:,
ws = [\t\n\r ]*
Bear in mind the following:
isspace()
. Whitespace in JSON is [\t\n\r ]
, but isspace()
also treats \v
(vertical tab) and \f
(form feed) as space. Although word has it that isdigit()
can accept more than just [0-9]
, should be okay to use here, as we assume input is in ASCII.\x7F
is technically a control character, but the JSON RFC doesn't mention it (it only mentions [\x00-\x1F]
), and most JSON parsers tend to accept \x7F
characters in strings. Because of this ambiguity, solutions may choose to either accept them or not.asked Feb 4, 2011 at 7:37
Joey AdamsJoey Adams10.6k33 gold badges3636 silver badges5656 bronze badges
\$\endgroup\$ 7 \$\begingroup\$ PHP : 297 285 264 253 characters<?=preg_match(<<<'R'
~([\h
]*)({(?1)((("([^"\\\0- ]| |\\(["\\/bfnrt]|u[\dA-Fa-f]{4}))*")(?1):(?1)((?5)|-?(0|[1-9]\d*)(\.\d+)?([Ee][+-]?\d+)?|(?2)|true|false|null))(((?1),(?1))(?4))*)?}|\[(?1)((?8)((?13)(?8))*)?(?1)])(?1)\z~A
R
,`cat`)?'Valid':'Invalid';
score: 300/300
This is a full, recursive implementation of the JSON grammar.
It works only on PHP ≥ 5.3 due to nowdoc syntax (heredoc would have required to double all \
).
Readable version:
(this is the same regex, with named capture groups and extended syntax):
#!/usr/bin/env php
<?php
$re = <<< 'RE'
~\A (?P<ws>[\t\n\r ])* (
(?P<object>\{ (?P>ws)*
(?P<members>
(?P<pair>
(?P<string>
"(?P<char>
[^"\\\x00-\x1F]
|\\(?P<escape>
["\\/bfnrt]
|u [0-9A-Fa-f]{4}
)
)*"
) (?P>ws)* : (?P>ws)* (?P<value>
(?P>string)
| (?P<number>-? (0 | [1-9][0-9]*) (\. [0-9]+)? ([Ee] [+-]? [0-9]+)? )
| (?P>object)
| (?P>array)
| true
| false
| null
)
) ( (?P>ws)* , (?P>ws)* (?P>pair) )*
)?
\})
|(?P<array>\[ (?P>ws)*
(?P<elements>
(?P>value) ( (?P>ws)* , (?P>ws)* (?P>value) )*
)?
(?P>ws)* \])
) (?P>ws)* \z~x
RE;
if (preg_match($re, stream_get_contents(STDIN))) {
echo 'Valid';
} else {
echo 'Invalid';
}
answered Feb 4, 2011 at 11:07
\$\endgroup\$ 3 \$\begingroup\$ Python - 340 314 299 292 charsimport re,os
r=x=re.sub
z=r('0\.0+','0',r('e[+-]?0+|[\t\n\r]',' ',r(r'"(\\["nrtb\\/]|[^\\"\0-\37])*"','1',r(r'true|false|null|\\u\w{4}|[1-9]\d*','0',os.read(0,99)))))
while z!=x:z,x=r('\{(1:\d)?(,\\1)*\}|\[(-?\d(,-?\d)*)?\]','0',r(' *([][{}:,]) *','\\1',z)),z
print['Inv','V'][z=='0']+'alid'
score
$ ./json-validate-test-suite.sh ./codegolf-474.py
score: 300/300
answered Feb 4, 2011 at 16:42
YOUYOU5,07122 gold badges2020 silver badges2323 bronze badges
\$\endgroup\$ \$\begingroup\$ Scala - 390 charsimport scala.util.parsing.combinator.JavaTokenParsers
object J extends JavaTokenParsers{def j=o|a
def o:Parser[Any]="{"~repsep(p,",")~"}"
def p=s~":"~v
def a:Parser[Any]="["~repsep(v,",")~"]"
def v=s|o|a|"true"|"false"|"null"
def s=stringLiteral
def n=floatingPointNumber}
object Main{def main(a:Array[String]){print(if(J.parseAll(J.j,readLine()).successful)"Valid"else"Invalid")}}
This is no-brainer soluton, using parser combinators. Written in 1 or 2 minutes, literally. Cannot get validator script, browser said that server not found.
answered Sep 26, 2012 at 17:16
Display NameDisplay Name65633 silver badges1111 bronze badges
\$\endgroup\$ 2 \$\begingroup\$ Bash + jq, 29 bytesjq -r '"Valid"'||echo Invalid
TIO's bash instance conveniently has jq installed for us so try it online at your leisure!
answered Sep 2, 2021 at 6:39
AviFSAviFS2,2011818 silver badges2727 bronze badges
\$\endgroup\$ 10Start asking to get answers
Find the answer to your question by asking.
Ask questionExplore related questions
See similar questions with these tags.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4