JSON 객체의 배열을 구문 분석하는 정규 표현?
문제
JSON 객체를 C#의 문자열 배열로 구문 분석하려고합니다. JSON 객체에서 배열을 추출 할 수 있지만 배열 문자열을 개별 개체 배열로 분할 할 수는 없습니다.
내가 가진 것은이 테스트 문자열입니다.
string json = "{items:[{id:0,name:\"Lorem Ipsum\"},{id:1,name"
+ ":\"Lorem Ipsum\"},{id:2,name:\"Lorem Ipsum\"}]}";
지금은 다음과 같은 정규 표현식을 사용하여 항목을 개별 객체로 나누고 있습니다. 지금은 두 번째 문제로 문제를 해결할 때까지 2 개의 별도의 정규 표현식입니다.
Regex arrayFinder = new Regex(@"\{items:\[(?<items>[^\]]*)\]\}"
, RegexOptions.ExplicitCapture);
Regex arrayParser = new Regex(@"((?<items>\{[^\}]\}),?)+"
, RegexOptions.ExplicitCapture);
그만큼 arrayFinder
Regex는 내가 기대하는 방식으로 작동하지만 이해하지 못하는 이유로 arrayParser
Regex는 전혀 작동하지 않습니다. 내가 원하는 것은 개별 항목을 자신의 문자열로 나누기 때문에 다음과 같은 목록을 얻는 것입니다.
{id:0,name:"Lorem Ipsum"}
{id:1,name:"Lorem Ipsum"}
{id:2,name:"Lorem Ipsum"}
이 목록이 string[]
배열 또는 a Group
또는 Match
컬렉션은 중요하지 않지만 물체를 분할하는 방법에 대해 혼란스러워합니다. 사용 arrayParser
그리고 json
위에 선언 된 문자열은 운이없는이 코드를 시도했습니다.
string json = "{items:[{id:0,name:\"Lorem Ipsum\"},{id:1,name"
+ ":\"Lorem Ipsum\"},{id:2,name:\"Lorem Ipsum\"}]}";
Regex arrayFinder = new Regex(@"\{items:\[(?<items>[^\]]*)\]\}"
, RegexOptions.ExplicitCapture);
Regex arrayParser = new Regex(@"((?<items>\{[^\}]\}),?)+"
, RegexOptions.ExplicitCapture);
string array = arrayFinder.Match(json).Groups["items"].Value;
// At this point the 'array' variable contains:
// {id:0,name:"Lorem Ipsum"},{id:1,name:"Lorem Ipsum"},{id:2,name:"Lorem Ipsum"}
// I would have expected one of these 2 lines to return
// the array of matches I'm looking for
CaptureCollection c = arrayParser.Match(array).Captures;
GroupCollection g = arrayParser.Match(array).Groups;
아무도 내가 뭘 잘못하고 있는지 볼 수 있습니까? 나는 이것에 완전히 붙어있다.
해결책
균형 잡힌 괄호는 말 그대로 정규식으로 처리 할 수없는 언어의 교과서 예입니다. JSON은 본질적으로 균형 잡힌 괄호와 다른 많은 것들이 있으며, 버팀대는 파렌으로 대체됩니다. 에서 공식 언어의 계층 구조, JSON은 상황이없는 언어입니다. 정규 표현식은 컨텍스트가없는 언어를 구문 분석 할 수 없습니다.
일부 시스템은 균형 잡힌 표현식을 처리하는 정규 표현식에 대한 확장을 제공합니다. 그러나 그들은 모두 못생긴 해킹, 모두 포송 할 수 없으며 궁극적으로 업무를위한 잘못된 도구입니다.
전문적인 작업에서는 거의 항상 기존 JSON 파서를 사용합니다. 교육 목적으로 직접 굴려 보려면 + - * / ()를 지원하는 간단한 산술 문법으로 시작하는 것이 좋습니다. (JSON은 복잡하지는 않지만 첫 번째 시도가 필요한 것보다 더 어렵게 만드는 탈출 규칙이 있습니다.) 기본적으로, 당신은 다음을 필요로합니다.
- 언어를 기호의 알파벳으로 분해하십시오
- 언어를 인식하는 상징의 관점에서 문맥이없는 문법을 작성하십시오.
- 문법을 Chomsky 정상 형태로 변환하거나 5 단계를 쉽게 만들기에 충분히 가까이
- 원시 텍스트를 입력 알파벳으로 변환하는 Lexer를 작성하십시오.
- Lexer의 출력을 취하고 구문 분석하고 어떤 종류의 출력을 생성하는 재귀 하강 파서를 작성하십시오.
이것은 거의 모든 대학에서 전형적인 3 학년 CS 과제입니다.
다음 단계는 재귀 파서에서 스택 오버 플로우를 트리거하는 데 JSON 문자열이 얼마나 복잡한 지 알아내는 것입니다. 그런 다음 쓸 수있는 다른 유형의 파서를 살펴보면 실제 세계에서 문맥이없는 언어를 구문 분석 해야하는 사람이 파서를 손으로 쓰는 대신 YACC 또는 ANTLR과 같은 도구를 사용하는 이유를 이해할 수 있습니다.
그것이 당신이 찾고 있던 것보다 더 많은 학습이라면, 당신은 비유한 JSON 파서를 자유롭게 사용해야합니다.
다른 팁
균형 잡힌 괄호는 말 그대로 정규식으로 처리 할 수없는 언어의 교과서 예입니다.
bla bla bla ... 이것을 확인하십시오 :
arrayParser = "(?<Key>[\w]+)":"?(?<Value>([\s\w\d\.\\\-/:_]+(,[,\s\w\d\.\\\-/:_]+)?)+)"?
이것은 나를 위해 작동합니다
빈 값과 일치하려면 마지막 '+'로 변경됩니다.
.NET 3.5를 사용하고 있습니까? 그렇다면 사용할 수 있습니다 DataContractJsonSerializer
이것을 구문 분석합니다. 이것을 직접 할 이유가 없습니다.
.NET 3.5를 사용하지 않는 경우 사용할 수 있습니다. 제이 록.
public Dictionary<string, string> ParseJSON(string s)
{
Regex r = new Regex("\"(?<Key>[\\w]*)\":\"?(?<Value>([\\s\\w\\d\\.\\\\\\-/:_\\+]+(,[,\\s\\w\\d\\.\\\\\\-/:_\\+]*)?)*)\"?");
MatchCollection mc = r.Matches(s);
Dictionary<string, string> json = new Dictionary<string, string>();
foreach (Match k in mc)
{
json.Add(k.Groups["Key"].Value, k.Groups["Value"].Value);
}
return json;
}
이 기능은 Lukasz 정규 표현식을 구현합니다. 나는 Incride + Char to Value Group에만 추가합니다 (라이브 Connect Auth Token을 구문 분석하기 위해 그것을 사용하기 때문에)
JSON은 일반적으로 정규 표현식으로 구문 분석 할 수 없습니다 (JSON CAN의 매우 단순화 된 변형은 JSON이 아니라 다른 것입니다).
JSON을 올바르게 구문 분석하려면 실제 파서가 필요합니다.
어쨌든, 왜 JSON을 전혀 구문 분석하려고합니까? 당신을 위해 그것을 할 수있는 수많은 라이브러리가 있으며, 당신의 코드보다 훨씬 나은 도서관이 있습니다. 문 위에 포스가있는 단어가있는 모퉁이에 바퀴 공장이있을 때 왜 바퀴를 재발 명합니까?