2013-06-12 4 views
8

JSON 데이터를 사용하는 클래스를 작성하는 방법을 안내하고 데이터를 읽을 수있는 간단한 버퍼링 된 목록으로 파싱하려고 시도 할 수 있습니까?기본 JSON 파싱 클래스를 작성하는 방법

Ex. JSON

{ name: 'John', age: 56 } 

는 빠르고 간단하게 만드는 데 도움이 될 구문 분석 방법을 작성하는 방법을 키 값 쌍

name John 
age 56 

의 테이블로 구문 분석 할 수 ..will?

기존 라이브러리를 제안하지 마십시오. JSON을 구문 분석하기위한 개념을 제공하십시오.

+2

왜 [Gson] (https://code.google.com/p/google-gson/)을 사용하지 않습니까? –

+2

이것은 유효한 JSON이 아닙니다! – fge

+2

[무엇을 시도해 봤습니까?] (http://mattgemmell.com/2008/12/08/what-have-you-tried/) 지금까지 묻지 말고? –

답변

18

이를 대답은 당신이 정말로 파서를 작성하고 필요한 노력을 할 준비가되어 있다고 가정합니다.

정식 JSON 사양부터 시작해야합니다. 나는 http://www.ietf.org/rfc/rfc4627.txt을 발견했다. 이것은 언어를 정확하게 정의합니다. 사양의 모든 것을 구현하고 테스트를 작성해야합니다. 파서는 (당신처럼) 잘못된 JSON을 처리하고 예외를 throw해야합니다.

파서를 작성하려면 중지하고 생각한 다음 수행하지 마십시오. 올바르게 작동하려면 많은 작업이 필요합니다. 여러분이 무엇을 하든지, 제대로 된 일을하십시오 - 불완전한 파서는 위협이며 절대 배포되어서는 안됩니다.

준수하는 코드를 작성해야합니다. 사양의 일부 구문은 다음과 같습니다. 당신이 그들을 이해하지 않으면 당신은주의 깊게 연구하고 이해하도록해야 할 것이다 ". JSON 텍스트가 유니 코드로 인코딩되어야합니다 기본 인코딩이 UTF-8입니다."

"JSON 구문 분석기는 JSON 문법을 준수하는 모든 텍스트를 허용해야합니다."

"인코딩 고려 사항 : UTF-8 인 경우 8 비트; 진 UTF-16 또는

JSON may be represented using UTF-8, UTF-16, or UTF-32. When JSON 
    is written in UTF-8, JSON is 8bit compatible. When JSON is 
    written in UTF-16 or UTF-32, the binary content-transfer-encoding 
    must be used. 

"

"UTF-32은 모든 문자가 이스케이프 할 수 있습니다합니다. 문자의 기본
다국어 평면 (U + FFFF 통해 U + 0000)의 경우,이 여섯 문자 시퀀스로서 표현
수있다 : 역방향 사선 뒤에 소문자 U 의해
따라 문자의 코드 포인트를
인 코드 네 개의 16 진수.
F의 16 진수 문자 A는 대문자 나 소문자 일 수 있습니다. 따라서 예를 들어,
한 개의 역 상보 문자 만 포함하는 문자열은
"\ u005C"로 표시 될 수 있습니다. "

당신은이를 잘 이해하고 있으며, 그 다음 다른 파서를 검토하고 그 중 하나는 적합성 테스트가 있는지. 자신의 응용 프로그램에 대한 이러한 대출.

을 여전히있는 경우, 파서를 작성하려면 예를 들어 JAVACC, CUP 및 필자가 선호하는 도구 인 ANTLR을 사용하는 것이 좋습니다. ANTLR은 매우 강력하지만 처음에는 사용하기가 어려울 수 있습니다 .Palboiled의 제안을 참조하십시오 .JSON은 상대적으로 간단하고 유용한 연습이 될 것입니다. 대부분의 파서 생성기는 JSON의 실행 가능 코드를 생성하거나 구문 분석 트리를 생성 할 수있는 완벽한 파서를 생성합니다.

당신이 그것을 들여다 볼 수 있다면, http://www.antlr.org/wiki/display/ANTLR3/JSON+Interpreter에 ANTLR을 사용하는 JSON 파서 생성기가 있습니다. 나는 또한 Parboiled parser-generator for JSON을 발견했습니다. 파서를 작성하는 주된 이유가 파서를 작성하는 방법을 배우는 경우, 이는 아마도 좋은 출발점 일 것입니다.

파서 - 생성기를 사용할 수 없거나 사용하고 싶지 않으면 자신 만의 파서를 만들어야합니다. 일반적으로 두 부분으로 나뉩니다 :

lexer/tokenizer. 이것은 언어 스펙에 정의 된 기본 프리미티브를 인식합니다. 이 경우 중괄호, 따옴표 등을 인식해야합니다. 아마도 숫자의 표현을 구성 할 수도 있습니다.

추상 구문 트리 (http://en.wikipedia.org/wiki/Abstract_syntax_tree, AST) 발생기. 여기서 JSON의 추상화를 나타내는 트리를 어셈블하는 코드를 작성합니다 (예 : 공백 및 중괄호는 삭제됨).

AST가있을 때 노드를 반복하고 원하는 출력을 만들어야합니다.

JSON과 같은 간단한 언어의 경우에도 구문 분석기 생성기를 작성하는 것은 많은 작업입니다.

+0

ANTLR은 빌드 프로세스를 많이 복잡하게한다는 단점이있다. Parboiled에는 그런 불리가 없다! 그것이 충분히 잘 알려져 있지 않은 동정. – fge

+0

@fge가 동의했습니다. 나는 한번 살펴 보겠다. –

4

"JSON"이 실제로 이와 같은 경우에는 먼저 야구 방망이를 가져 와서 제작자를 머리 위로 두드려야합니다. 진지하게. (왜?) 구현은 다음 인수로 CharBuffer 및지도 빌더 걸릴 것

public interface MyParser 
{ 
    boolean parse() 
     throws MyParsingException; 
    MyParser next(); 
} 

당신이 정말로 자신의 클래스를 작성하는 주장 경우

, 당신은 예를 들어이 같은 인터페이스를 사용할 수 있습니다 수업; 당신이 할 것 구문 분석 :

final CharBuffer buf = CharBuffer.wrap(yourSource); 
final MyMapBuilder builder = new MyMapBuilder(); 

MyParser parser = new OpenBracketParser(buf, builder); 

while (parser.parse()) 
    parser = parser.next(); 

// result is builer.build() 

이 있지만 하나의 예입니다 ...

둘째 솔루션, 기존의 분석 도구를 사용하려면; 이 경우에는 Parboiled을보십시오. 순수 자바로 문법을 작성하기 때문에 antlr, jflex 또는 다른 것들보다 사용하기가 훨씬 쉽습니다. 마지막으로

, 당신이 그 정도로 충분 결정하고, JSON 라이브러리를 사용하기로 결정한 경우 (당신이 정말로 그렇게한다), 심지어 잘못된 JSON 읽을 수있는 Jackson로 이동합니다

public static void main(final String... args) 
    throws IOException 
{ 
    final ObjectMapper mapper = new ObjectMapper() 
     .configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true) 
     .configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); 

    final JsonNode node = mapper.readTree("{name: 'John'}"); 
    System.out.println(node); // {"name":"John"} 
} 
+0

그는 아무 라이브러리도 말하지 않았다. – BLaZuRE

+1

어 ... 글쎄, 각 독약에, 나는 추측한다. – fge

0
public abstract class AbstractMessageObject { 
    public String toString() { 
    Gson gson = new Gson(); 
    //here mapping Object class name is prefixed to json message so otherwise knows the mapping object 
    return "^" + this.getClass().getName() + "^" + gson.toJson(this); 
    } 
} 

AbstractMessageObject을 확장하여 빈을 만들 수 있습니다. 해당 객체를 JSON으로 구문 분석 할 때마다 toString 메소드 만 호출하면됩니다.

+1

OP가 라이브러리를 지정하지 않았습니다. :-( –

3

필자는 이전에 이것을 작성했습니다.단계 :

  1. JSON 텍스트를 나타내는 문자열을 가져옵니다.

  2. JsonToken 클래스를 만듭니다. 나는 JToken이라고 부른다.

  3. 1 단계에서 전체 텍스트를 읽고 JToken을 구문 분석하십시오.

  4. JToken을 반복적으로 그룹화하고 중첩합니다.

  5. 시도하십시오. 간단하고 균일하게 유지하십시오. 모든 JToken 노드에는 0 개 이상의 자식을 가질 수있는 자식 배열이 있습니다. 노드가 배열 인 경우 배열로 플래그를 지정합니다. 자식 배열은 자식이 OBJECT 또는 ARRAY 인 경우 노드의 자식에 사용됩니다. 유일한 변경 사항은 플래그가 지정된 것입니다. 또한 모든 값을 문자열 유형으로 유지하십시오. 그렇게하면 "value"라는 노드에 단일 구성원 만 있으면되므로 모든 노력이 끝난 후 올바른 데이터 형식으로 해석 될 수 있습니다.

  6. 방어 코딩 및 단위 테스트를 사용하십시오. 파서의 모든 구성 요소에 대한 테스트를 작성합니다. 3 시간 동안 실수로 버그를 잡는 데 3 시간을 소비해야한다고 생각하는 편집증적인 방식으로 코드를 작성하는 데 3 시간을 소비하는 것이 좋습니다. 충분히 편집 적으로 코드를 작성하면 디버깅 할 때 좌절하는 시간을 거의 갖지 않게됩니다.

예제 코드 : 내가 code-eval.com에 쉽게 (아이러니하게도) 도전을하고 있었다. json 메뉴 파싱 문제가있었습니다. 나는 내게 코드 챌린지의 전체 점 이 알고리즘 문제 해결 능력을 테스트하기 때문에 어떤 내장 함수를 사용하는 것이 속임수 일 것이라고 생각했다. 도전은 여기에 있습니다 : 자바 스크립트 처음부터 내장 파서를 사용하여이 문제를 통과 https://www.codeeval.com/open_challenges/102/

내 코드 :

CODE: https://pastebin.com/BReK9iij 
Was not able to post it on stack-overflow because it is too much code. 
Put it in a non-expiring paste-bin post. 

참고 :이 코드는 몇 가지 개선을 사용할 수 있습니다. 일부는 매우 비효율적이며 이며 유니 코드에서는 작동하지 않습니다.

일부 비표준 방식으로 JSON을 해석하지 않는 한 독자적인 JSON 구문 분석기를 작성하지 않는 것이 좋습니다.

예 : 현재 JSONedit을 사용하여 텍스트 기반 모험을위한 분기를 구성하고 있습니다. JSON 파일 형식은 압축 적이기 때문에 뷰어를 사용하면 항목을 확장하고 계약 할 수 있습니다. GOLang과 함께 제공되는 표준 파서는 정보를 해석하려는 방식으로 정보를 해석하지 않으므로 필자는 자체 파서를 작성하고 있습니다.