Viết trình xác nhận JSON


12

Viết chương trình xác định xem đầu vào của nó có phải là JSON hợp lệ hay không .

  • Đầu vào: văn bản ASCII:[\x00-\x7F]*

    Lưu ý: nếu ASCII có vấn đề, vui lòng sử dụng mã hóa khác, nhưng chỉ ra nó trong bài viết của bạn.

  • Đầu ra: Valid hoặc Invalid. Trailing dòng mới có thể được bỏ qua.

  • Thí dụ:

    $ echo '{"key": "value"}' | ./json-validate
    Valid
    $ echo '{key: "value"}' | ./json-validate
    Invalid
    
  • Quy tắc:

    • Không sử dụng thư viện phân tích cú pháp JSON.
    • Các giải pháp đúng một phần được cho phép, nhưng nhăn mặt.
    • Gửi điểm số bộ thử nghiệm của bạn (xem bên dưới).

Các ngắn nhất đúng thắng giải pháp.

Vui lòng chạy json-validate-test-suite.sh trên chương trình của bạn và gửi điểm số của bạn. Thí dụ:

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

Tài nguyên:

  • json.org - Định nghĩa ngắn gọn về ngữ pháp JSON với các hình ảnh dễ theo dõi.
  • RFC 4627 - Đặc tả JSON
  • json-validate.c - Một triển khai 200 dòng vượt qua testsuite.

Ngữ pháp JSON như sau:

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

Ngoài ra, khoảng trắng có thể xuất hiện trước hoặc sau bất kỳ trong sáu ký tự cấu trúc {}[]:,

ws = [\t\n\r ]*

Hãy ghi nhớ những điều sau:

  • Cẩn thận với các chức năng như isspace(). Khoảng trắng trong JSON là [\t\n\r ], nhưng isspace()cũng coi \v(tab dọc) và \f(nguồn cấp dữ liệu biểu mẫu) là không gian. Mặc dù từ này isdigit()có thể chấp nhận nhiều hơn là[0-9] , nhưng sẽ ổn khi sử dụng ở đây, vì chúng tôi giả sử đầu vào là ở ASCII.
  • \x7Fvề mặt kỹ thuật là một ký tự điều khiển, nhưng JSON RFC không đề cập đến nó (nó chỉ đề cập đến [\x00-\x1F]) và hầu hết các trình phân tích cú pháp JSON có xu hướng chấp nhận các \x7Fký tự trong chuỗi. Vì sự mơ hồ này, các giải pháp có thể chọn chấp nhận chúng hoặc không.

7
Ghi chú "giải pháp đúng một phần được cho phép" của bạn đang khiến tôi mơ ước trích xuất một biểu thức chính quy từ thuật toán di truyền. Tôi phải mất trí.
JB

@JB: Điều đó thật tuyệt vời.
Joey Adams

Chỉ tò mò, tại sao lại {key: "value"}coi JSON không hợp lệ? Nó là javascript hợp lệ.
HoLyVieR

@HoLyVieR: Tôi tưởng tượng như vậy nên JSON sẽ dễ phân tích cú pháp hơn và ít mơ hồ hơn đối với người triển khai. Tôi cũng không chắc là tôi thích hạn chế này.
Joey Adams

Bất cứ ai cũng có một bản sao của kịch bản xác nhận?
Armand

Câu trả lời:


7

PHP: 297 285 264 253 ký tự

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

điểm: 300/300

Đây là một triển khai đầy đủ, đệ quy của ngữ pháp JSON.

Nó chỉ hoạt động trên PHP ≥ 5.3 do nowdoc cú pháp (heredoc sẽ có yêu cầu cho tất cả các đôi\ ).

Phiên bản dễ đọc:

(đây là regex tương tự, với các nhóm chụp được đặt tên và cú pháp mở rộng):

#!/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

Bạn cần bao gồm <?phpIMO.
kẻ hèn nhát ẩn danh

Thêm. 264 ký tự ngay bây giờ :-)
Arnaud Le Blanc

5

Python - 340 314 299 292 ký tự

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'

ghi bàn

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

3

Scala - 390 ký tự

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

Đây là soluton không có trí tuệ, sử dụng kết hợp trình phân tích cú pháp. Viết trong 1 hoặc 2 phút, theo nghĩa đen. Không thể lấy tập lệnh xác thực, trình duyệt cho biết không tìm thấy máy chủ.


trông giống như một giải pháp thú vị; liên kết trình xác nhận đã được cố định.
Armand

Có một cách đơn giản để làm điều đó trên Windows? (không có cygwin hoặc dị giáo tương tự)
Tên hiển thị
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.