Schreiben Sie einen JSON-Validator


12

Schreiben Sie ein Programm, das feststellt, ob seine Eingabe JSON- gültig ist .

  • Eingabe: ASCII-Text:[\x00-\x7F]*

    Hinweis: Wenn ASCII problematisch ist, können Sie eine andere Codierung verwenden, diese jedoch in Ihrem Beitrag angeben.

  • Ausgabe: Valid oder Invalid. Nachgestellte Zeilenumbrüche können weggelassen werden.

  • Beispiel:

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

    • Verwenden Sie keine JSON-Analysebibliothek.
    • Teilkorrekte Lösungen sind erlaubt, aber verpönt.
    • Veröffentlichen Sie Ihre Testsuite (siehe unten).

Die kürzeste richtige Lösung gewinnt.

Bitte führen Sie json-validate-test-suite.sh in Ihrem Programm aus und geben Sie Ihre Punktzahl ein. Beispiel:

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

Ressourcen:


Die JSON-Grammatik lautet wie folgt:

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

Außerdem kann vor oder nach den sechs Strukturzeichen ein Leerzeichen stehen {}[]:,

ws = [\t\n\r ]*

Beachten Sie Folgendes:

  • Seien Sie vorsichtig mit Funktionen wie isspace(). Whitespace in JSON ist [\t\n\r ], isspace()behandelt aber auch \v(vertikale Registerkarte) und \f(Formularvorschub) als Leerzeichen. Obwohl Word es hat, das mehr als nur akzeptierenisdigit() kann , sollte es in Ordnung sein, es hier zu verwenden, da wir davon ausgehen, dass die Eingabe in ASCII erfolgt.[0-9]
  • \x7Fist technisch gesehen ein Steuerzeichen, wird jedoch im JSON-RFC nicht erwähnt (nur erwähnt [\x00-\x1F]), und die meisten JSON-Parser akzeptieren \x7FZeichen in Zeichenfolgen. Aufgrund dieser Mehrdeutigkeit können die Lösungen entscheiden, ob sie diese akzeptieren oder nicht.

7
Ihre Anmerkung "teilweise korrekte Lösungen erlaubt" lässt mich träumen, einen regulären Ausdruck aus einem genetischen Algorithmus zu extrahieren. Ich muss verrückt sein.
JB

@JB: Das wäre großartig.
Joey Adams

Nur neugierig, warum wird {key: "value"}JSON für ungültig erklärt? Es ist gültiges Javascript.
HoLyVieR

@HoLyVieR: Ich stelle mir vor, dass JSON für Implementierer einfacher zu analysieren und weniger mehrdeutig ist. Ich bin mir auch nicht sicher, ob mir diese Einschränkung gefällt.
Joey Adams

Hat jemand eine Kopie des Validator-Skripts?
Armand

Antworten:


7

PHP: 297 285 264 253 Zeichen

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

Punktzahl: 300/300

Dies ist eine vollständige, rekursive Implementierung der JSON-Grammatik.

Aufgrund der nowdoc- Syntax funktioniert es nur mit PHP ≥ 5.3 (heredoc hätte alles verdoppeln müssen \).

Lesbare Version:

(Dies ist der gleiche reguläre Ausdruck mit benannten Erfassungsgruppen und erweiterter 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';
}

Beeindruckend. `` `` `
Nathan Osman

Sie müssen die <?phpIMO einbeziehen.
Anonymer Feigling

Hinzugefügt. 264 Zeichen jetzt :-)
Arnaud Le Blanc

5

Python - 340 314 299 292 Zeichen

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'

Ergebnis

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

3

Scala - 390 Zeichen

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

Dies ist eine einfache Lösung, die Parser-Kombinatoren verwendet. Im wahrsten Sinne des Wortes in 1 oder 2 Minuten geschrieben. Das Überprüfungsskript kann nicht abgerufen werden. Der Browser hat gemeldet, dass der Server nicht gefunden wurde.


sieht nach einer interessanten Lösung aus; Validator-Link wurde behoben.
Armand

Gibt es eine einfache Möglichkeit, dies unter Windows zu tun? (ohne Cygwin oder ähnliche Häresie)
Anzeigename
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.