JSON을 검증하기 위한 정규식
json을 검증할 수 있는 Regex를 찾고 있습니다.
저는 Regex에 매우 익숙하지 않기 때문에 Regex를 사용한 해석은 좋지 않다는 것을 충분히 알고 있습니다만, 검증에 사용할 수 있습니까?
예, 완전한 regex 검증이 가능합니다.
대부분의 최신 regex 구현에서는 완전한 JSON 직렬 구조를 확인할 수 있는 재귀 정규식 표현을 허용합니다.json.org 사양에서는 매우 간단합니다.
$pcre_regex = '
/
(?(DEFINE)
(?<number> -? (?= [1-9]|0(?!\d) ) \d+ (\.\d+)? ([eE] [+-]? \d+)? )
(?<boolean> true | false | null )
(?<string> " ([^"\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9a-f]{4} )* " )
(?<array> \[ (?: (?&json) (?: , (?&json) )* )? \s* \] )
(?<pair> \s* (?&string) \s* : (?&json) )
(?<object> \{ (?: (?&pair) (?: , (?&pair) )* )? \s* \} )
(?<json> \s* (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) ) \s* )
)
\A (?&json) \Z
/six
';
PCRE 함수와 함께 PHP에서 매우 잘 작동합니다.Perl에서는 변경되지 않고 동작합니다.또, 다른 언어에도 대응할 수 있습니다.또, JSON 테스트 케이스에서도 성공합니다.
RFC4627 검증 간소화
보다 심플한 접근방식은 RFC4627 섹션6에서 규정되어 있는 최소한의 일관성 체크입니다.다만, 이것은 시큐러티 테스트와 기본적인 무효 예방책의 목적으로만 행해지고 있습니다.
var my_JSON_object = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(
text.replace(/"(\\.|[^"\\])*"/g, ''))) &&
eval('(' + text + ')');
예, 정규 표현식은 정규 언어만 일치시킬 수 있다는 것은 일반적인 오해입니다.실제로 PCRE 함수는 일반 언어보다 훨씬 더 많이 일치할 수 있으며, 컨텍스트가 없는 일부 언어에도 일치할 수 있습니다.RegExps에 대한 위키피디아의 글은 그것에 대한 특별한 섹션을 가지고 있다.
JSON은 PCRE를 사용하여 여러 가지 방법으로 인식할 수 있습니다!@syslog는 이름 있는 서브패턴과 백레퍼런스를 사용한1개의 훌륭한 솔루션을 나타내고 있습니다.그리고 그는 재귀적 패턴을 이용한 해결책이 있어야 한다고 언급했다. (?R)
PHP의 regexp에 관한 것입니다.
$regexString = '"([^"\\\\]*|\\\\["\\\\bfnrt\/]|\\\\u[0-9a-f]{4})*"';
$regexNumber = '-?(?=[1-9]|0(?!\d))\d+(\.\d+)?([eE][+-]?\d+)?';
$regexBoolean= 'true|false|null'; // these are actually copied from Mario's answer
$regex = '/\A('.$regexString.'|'.$regexNumber.'|'.$regexBoolean.'|'; //string, number, boolean
$regex.= '\[(?:(?1)(?:,(?1))*)?\s*\]|'; //arrays
$regex.= '\{(?:\s*'.$regexString.'\s*:(?1)(?:,\s*'.$regexString.'\s*:(?1))*)?\s*\}'; //objects
$regex.= ')\Z/is';
하고 (?1)
(?R)
왜냐하면 후자는 전체 패턴을 참조하지만 우리는\A
★★★★★★★★★★★★★★★★★」\Z
서브패턴 내에서 사용하지 않는 시퀀스입니다. (?1)
괄호로 의 regexp에 대한 )( )
는 「」로 시작하지 않습니다.?:
RegExp는 268자입니다.
/\A("([^"\\]*|\\["\\bfnrt\/]|\\u[0-9a-f]{4})*"|-?(?=[1-9]|0(?!\d))\d+(\.\d+)?([eE][+-]?\d+)?|true|false|null|\[(?:(?1)(?:,(?1))*)?\s*\]|\{(?:\s*"([^"\\]*|\\["\\bfnrt\/]|\\u[0-9a-f]{4})*"\s*:(?1)(?:,\s*"([^"\\]*|\\["\\bfnrt\/]|\\u[0-9a-f]{4})*"\s*:(?1))*)?\s*\})\Z/is
어쨌든, 이것은 「테크놀로지 데모」로서 취급할 필요가 있습니다.이치노을 PHP를 합니다.json_decode()
(@Epcylon에서 설명한 것과 동일)그 JSON을 사용하는 경우(검증된 경우), 이것이 최선의 방법입니다.
JSON(네스트된 JSON)의 {...}
-s) regex는 검증에 적합하지 않습니다.물론 일부 regex 플레이버는 반복적으로 패턴과* 일치할 수 있지만(또한 JSON과 일치할 수 있음) 결과 패턴은 보기에도 끔찍하며 프로덕션 코드 IMO에 절대 사용되지 않습니다.
* 단, 많은 regex 구현은 재귀 패턴을 지원하지 않습니다.일반적으로 사용되는 프로그래밍 언어 중 Perl , 는 재귀 패턴을 지원합니다.NET, PHP 및 Ruby 1.9.2
@fails의 답변을 시도했지만, JSON.org에서 테스트 스위트를 다운로드(fail1.json, fail18.json, fail25.json, fail27.json)한 4개의 테스트에 실패했기 때문에 잘 되지 않았습니다.
를 해 보니, ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★.fail1.json
는 실제로 올바른 것입니다(매뉴얼의 주기에 따라 RFC-7159의 유효한 문자열도 유효한 JSON입니다).파일fail18.json
을 가진 JSON이 때문입니다.실제로 깊은 네스트의 정확한 JSON이 포함되어 있기 때문입니다.
[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]
두 남았습니다.fail25.json
★★★★★★★★★★★★★★★★★」fail27.json
:
[" tab character in string "]
그리고.
["line
break"]
둘 다 잘못된 문자를 포함합니다.그래서 패턴을 다음과 같이 업데이트했습니다(문자열 서브패턴 업데이트).
$pcreRegex = '/
(?(DEFINE)
(?<number> -? (?= [1-9]|0(?!\d) ) \d+ (\.\d+)? ([eE] [+-]? \d+)? )
(?<boolean> true | false | null )
(?<string> " ([^"\n\r\t\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9a-f]{4} )* " )
(?<array> \[ (?: (?&json) (?: , (?&json) )* )? \s* \] )
(?<pair> \s* (?&string) \s* : (?&json) )
(?<object> \{ (?: (?&pair) (?: , (?&pair) )* )? \s* \} )
(?<json> \s* (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) ) \s* )
)
\A (?&json) \Z
/six';
따라서 이제 json.org의 모든 법률시험에 합격할 수 있게 되었습니다.
JSON의 문서를 보면 적합성을 확인하는 것이 목적이라면 regex는 단순히 세 부분으로 나눌 수 있습니다.
- 문자열은 다음 중 하나로 시작하고 끝납니다.
[]
★★★★★★★★★★★★★★★★★」{}
[{\[]{1}
...[}\]]{1}
- 그리고.
- 문자는 허용된 JSON 제어 문자입니다(1개만).
- ........
[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]
- 또는 에 포함된 문자 세트
""
- ........
".*?"
함께 : ★★★★★★★★★★★★★★★★★★:[{\[]{1}([,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]|".*?")+[}\]]{1}
에 JSON이 포함되어 있는 newline
후, 「 」, 「 」를 선택합니다.singleline
regex가 "regex" 로 되도록 ..
newline
모든 부정한 JSON에서 실패하는 것은 아니지만 기본 JSON 구조가 비활성화되면 실패합니다.이것은 파서에 전달하기 전에 기본적인 건전성을 검증하는 간단한 방법입니다.
Mario의 솔루션의 Ruby 실장을 작성했습니다.그것은 다음과 같이 동작합니다.
# encoding: utf-8
module Constants
JSON_VALIDATOR_RE = /(
# define subtypes and build up the json syntax, BNF-grammar-style
# The {0} is a hack to simply define them as named groups here but not match on them yet
# I added some atomic grouping to prevent catastrophic backtracking on invalid inputs
(?<number> -?(?=[1-9]|0(?!\d))\d+(\.\d+)?([eE][+-]?\d+)?){0}
(?<boolean> true | false | null ){0}
(?<string> " (?>[^"\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9a-f]{4} )* " ){0}
(?<array> \[ (?> \g<json> (?: , \g<json> )* )? \s* \] ){0}
(?<pair> \s* \g<string> \s* : \g<json> ){0}
(?<object> \{ (?> \g<pair> (?: , \g<pair> )* )? \s* \} ){0}
(?<json> \s* (?> \g<number> | \g<boolean> | \g<string> | \g<array> | \g<object> ) \s* ){0}
)
\A \g<json> \Z
/uix
end
########## inline test running
if __FILE__==$PROGRAM_NAME
# support
class String
def unindent
gsub(/^#{scan(/^(?!\n)\s*/).min_by{|l|l.length}}/u, "")
end
end
require 'test/unit' unless defined? Test::Unit
class JsonValidationTest < Test::Unit::TestCase
include Constants
def setup
end
def test_json_validator_simple_string
assert_not_nil %s[ {"somedata": 5 }].match(JSON_VALIDATOR_RE)
end
def test_json_validator_deep_string
long_json = <<-JSON.unindent
{
"glossary": {
"title": "example glossary",
"GlossDiv": {
"id": 1918723,
"boolean": true,
"title": "S",
"GlossList": {
"GlossEntry": {
"ID": "SGML",
"SortAs": "SGML",
"GlossTerm": "Standard Generalized Markup Language",
"Acronym": "SGML",
"Abbrev": "ISO 8879:1986",
"GlossDef": {
"para": "A meta-markup language, used to create markup languages such as DocBook.",
"GlossSeeAlso": ["GML", "XML"]
},
"GlossSee": "markup"
}
}
}
}
}
JSON
assert_not_nil long_json.match(JSON_VALIDATOR_RE)
end
end
end
"문자열과 숫자"의 경우 숫자에 대한 부분 정규 표현은 다음과 같습니다.
-?(?:0|[1-9]\d*)(?:\.\d+)(?:[eE][+-]\d+)?
대신 다음과 같이 해야 합니다.
-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+\-]?\d+)?
이며, 이 숫자에서 탈출하는 이 더 할 수 .-
symbol symbol in in의 [+-]
JSON 어레이의 후행 콤마로 인해 Perl 5.16이 중단되었습니다.아마도 계속 역추적이 이루어졌기 때문입니다.백트랙 종료 지시문을 추가해야 했습니다.
(?<json> \s* (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) )(*PRUNE) \s* )
^^^^^^^^
해서 '아닌 ('선택사항')이*
★★★★★★★★★★★★★★★★★」?
다른 것으로 식별하기 위해 역추적을 시도해서는 안 됩니다.
JSONArray가 아닌 단순 JSON을 검증하는 정규식
키(문자열): value(string, value, [{key: value}, {key: value}), {key: value}를 확인합니다.
^\{(\s|\n\s)*(("\w*"):(\s)*("\w*"|\d*|(\{(\s|\n\s)*(("\w*"):(\s)*("\w*(,\w+)*"|\d{1,}|\[(\s|\n\s)*(\{(\s|\n\s)*(("\w*"):(\s)*(("\w*"|\d{1,}))((,(\s|\n\s)*"\w*"):(\s)*("\w*"|\d{1,}))*(\s|\n)*\})){1}(\s|\n\s)*(,(\s|\n\s)*\{(\s|\n\s)*(("\w*"):(\s)*(("\w*"|\d{1,}))((,(\s|\n\s)*"\w*"):(\s)*("\w*"|\d{1,}))*(\s|\n)*\})?)*(\s|\n\s)*\]))((,(\s|\n\s)*"\w*"):(\s)*("\w*(,\w+)*"|\d{1,}|\[(\s|\n\s)*(\{(\s|\n\s)*(("\w*"):(\s)*(("\w*"|\d{1,}))((,(\s|\n\s)*"\w*"):(\s)*("\w*"|\d{1,}))*(\s|\n)*\})){1}(\s|\n\s)*(,(\s|\n\s)*\{(\s|\n\s)*(("\w*"):(\s)*(("\w*"|\d{1,}))((,(\s|\n\s)*"\w*"):("\w*"|\d{1,}))*(\s|\n)*\})?)*(\s|\n\s)*\]))*(\s|\n\s)*\}){1}))((,(\s|\n\s)*"\w*"):(\s)*("\w*"|\d*|(\{(\s|\n\s)*(("\w*"):(\s)*("\w*(,\w+)*"|\d{1,}|\[(\s|\n\s)*(\{(\s|\n\s)*(("\w*"):(\s)*(("\w*"|\d{1,}))((,(\s|\n\s)*"\w*"):(\s)*("\w*"|\d{1,}))*(\s|\n)*\})){1}(\s|\n\s)*(,(\s|\n\s)*\{(\s|\n\s)*(("\w*"):(\s)*(("\w*"|\d{1,}))((,(\s|\n\s)*"\w*"):(\s)*("\w*"|\d{1,}))*(\s|\n)*\})?)*(\s|\n\s)*\]))((,(\s|\n\s)*"\w*"):(\s)*("\w*(,\w+)*"|\d{1,}|\[(\s|\n\s)*(\{(\s|\n\s)*(("\w*"):(\s)*(("\w*"|\d{1,}))((,(\s|\n\s)*"\w*"):(\s)*("\w*"|\d{1,}))*(\s|\n)*\})){1}(\s|\n\s)*(,(\s|\n\s)*\{(\s|\n\s)*(("\w*"):(\s)*(("\w*"|\d{1,}))((,(\s|\n\s)*"\w*"):("\w*"|\d{1,}))*(\s|\n)*\})?)*(\s|\n\s)*\]))*(\s|\n\s)*\}){1}))*(\s|\n)*\}$
이 JSON에서 검증하는 샘플 데이터
{
"key":"string",
"key": 56,
"key":{
"attr":"integer",
"attr": 12
},
"key":{
"key":[
{
"attr": 4,
"attr": "string"
}
]
}
}
위에서 기술한 바와 같이 사용하는 언어에 JSON 라이브러리가 포함되어 있는 경우 문자열 디코딩을 시도하고 실패 시 예외/오류를 파악합니다.언어가 그렇지 않은 경우(FreeMarker와 같은 경우만 해당) 다음 regex는 최소한 매우 기본적인 검증을 제공할 수 있습니다(PHP/PCRE가 더 많은 사용자에게 테스트/사용 가능하도록 작성되어 있습니다).이 솔루션은 일반적인 솔루션만큼 완벽하지는 않지만, 그렇게 무섭지도 않습니다 =).
~^\{\s*\".*\}$|^\[\n?\{\s*\".*\}\n?\]$~s
간단한 설명:
// we have two possibilities in case the string is JSON
// 1. the string passed is "just" a JSON object, e.g. {"item": [], "anotheritem": "content"}
// this can be matched by the following regex which makes sure there is at least a {" at the
// beginning of the string and a } at the end of the string, whatever is inbetween is not checked!
^\{\s*\".*\}$
// OR (character "|" in the regex pattern)
// 2. the string passed is a JSON array, e.g. [{"item": "value"}, {"item": "value"}]
// which would be matched by the second part of the pattern above
^\[\n?\{\s*\".*\}\n?\]$
// the s modifier is used to make "." also match newline characters (can happen in prettyfied JSON)
제가 실수로 이걸 놓쳤다면댓글을 달아주셔서 감사합니다
여기서 문자열의 유효성을 확인하기 위한 regexp:
^\"([^\"\\]*|\\(["\\\/bfnrt]{1}|u[a-f0-9]{4}))*\"$
이게 6년 전 일이라는 걸 알아요.하지만, 여기 있는 누구도 언급하지 않은 해결책이 있습니다. 이 솔루션은 리게이징보다 훨씬 쉽습니다.
function isAJSON(string) {
try {
JSON.parse(string)
} catch(e) {
if(e instanceof SyntaxError) return false;
};
return true;
}
언급URL : https://stackoverflow.com/questions/2583472/regex-to-validate-json
'programing' 카테고리의 다른 글
도커의 Word press: 마운트된 볼륨에 디렉터리를 만들 수 없습니다. (0) | 2023.03.08 |
---|---|
mongoimport를 사용하여 파일에서 mongodb로 json 가져오기 (0) | 2023.03.08 |
기능 구성요소의 기능은 어디로 이동해야 합니까? (0) | 2023.03.08 |
AngualrJ: html 갱신 시 데이터 유지 (0) | 2023.03.08 |
Oracle 더하기(+) 표기법과 ANSI JOIN 표기법의 차이점 (0) | 2023.03.08 |