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.