JSON 유효성 검사기 작성


12

입력이 유효한 JSON 인지 판별하는 프로그램을 작성하십시오 .

  • 입력 : ASCII 텍스트 :[\x00-\x7F]*

    참고 : ASCII에 문제가있는 경우 다른 인코딩을 자유롭게 사용하지만 게시물에 표시하십시오.

  • 출력 : Valid 또는 Invalid. 후행 줄 바꿈은 생략 될 수 있습니다.

  • 예:

    $ echo '{"key": "value"}' | ./json-validate
    Valid
    $ echo '{key: "value"}' | ./json-validate
    Invalid
    
  • 규칙 :

    • JSON 구문 분석 라이브러리를 사용하지 마십시오.
    • 부분적으로 올바른 솔루션은 허용되지만 눈살을 찌푸리게합니다.
    • 테스트 스위트 점수를 게시하십시오 (아래 참조).

짧은 올바른 솔루션 승리.

프로그램에서 json-validate-test-suite.sh 를 실행 하고 점수를 게시하십시오. 예:

$ ./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

자원:

  • json.org- 따라 가기 쉬운 그림으로 JSON 문법을 간결하게 정의합니다.
  • RFC 4627 -JSON 사양
  • json-validate.c- 테스트 슈트를 통과하는 200 라인 구현.

JSON 문법은 다음과 같습니다.

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]+)?

또한 공백은 6 개의 구조 문자 앞뒤에 나타날 수 있습니다. {}[]:,

ws = [\t\n\r ]*

다음을 명심하십시오.

  • 와 같은 기능에주의하십시오 isspace(). JSON의 공백은 [\t\n\r ]있지만, isspace()또한 취급 \v(수직 탭)와 \f공간으로 (용지 공급). 단어가 그것을 가지고 있지만 isdigit()많은 것보다는 다만 동의를[0-9] 우리가 입력 ASCII에서 가정으로, 여기에 사용하는 것이 괜찮을 것 같네요.
  • \x7F는 기술적으로 제어 문자이지만 JSON RFC는이를 언급하지 않으며 (만 언급 [\x00-\x1F]) 대부분의 JSON 파서는 \x7F문자열의 문자 를 허용하는 경향이 있습니다. 이러한 모호성 때문에 솔루션은이를 수용할지 여부를 선택할 수 있습니다.

7
"부분적으로 올바른 해결책이 허용되었습니다"라는 메모는 유전자 알고리즘에서 정규식을 추출하는 것을 꿈꾸고 있습니다. 나는 미쳐야한다.
JB

@JB : 대단 할 것입니다.
Joey Adams

궁금한 점은 왜 {key: "value"}유효하지 않은 JSON이라고 생각합니까? 유효한 자바 스크립트입니다.
HoLyVieR

@ HoLyVieR : JSON이 구문 분석하기 쉽고 구현 자에게는 모호하지 않을 것이라고 생각합니다. 이 제한이 마음에 들지 않습니다.
Joey Adams

유효성 검사기 스크립트의 사본이 있습니까?
Armand

답변:


7

PHP : 297 285 264 253 자

<?=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';

점수 : 300/300

이것은 JSON 문법의 전체, 재귀 적 구현입니다.

nowdoc 구문 으로 인해 PHP ≥ 5.3에서만 작동 합니다 ( heredoc 은 모두 두 배가 필요했습니다 \).

읽을 수있는 버전 :

(이것은 명명 된 캡처 그룹과 확장 구문을 가진 동일한 정규식입니다) :

#!/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';
}

와. ``````
Nathan Osman

<?phpIMO 를 포함해야합니다 .
익명 겁쟁이

추가되었습니다. 264 chars :-)
Arnaud Le Blanc

5

파이썬 - 340 개 314 299 292 문자

import 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'

점수

$ ./json-validate-test-suite.sh ./codegolf-474.py
score: 300/300

3

스칼라-390 자

import 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")}}

파서 결합기를 사용하는 브레이 너가없는 솔루 톤입니다. 말 그대로 1 ~ 2 분 안에 작성되었습니다. 브라우저가 서버를 찾을 수 없다고 유효성 검사기 스크립트를 가져올 수 없습니다.


흥미로운 해결책처럼 보입니다. 유효성 검사기 링크가 수정되었습니다.
Armand

Windows에서 간단한 방법이 있습니까? (cygwin 또는 이와 유사한 이단이없는 경우)
표시 이름
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.