| package main; |
| |
| import org.codehaus.jackson.*; |
| |
| import java.io.IOException; |
| |
| /** |
| * Set of basic unit tests for verifying that the basic parser |
| * functionality works as expected. |
| */ |
| public class TestJsonParser |
| extends BaseTest |
| { |
| |
| /** |
| * This basic unit test verifies that example given in the Json |
| * specification (RFC-4627 or later) is properly parsed at |
| * high-level, without verifying values. |
| */ |
| public void testSpecExampleSkipping() |
| throws Exception |
| { |
| doTestSpec(false); |
| } |
| |
| /** |
| * Unit test that verifies that the spec example JSON is completely |
| * parsed, and proper values are given for contents of all |
| * events/tokens. |
| */ |
| public void testSpecExampleFully() |
| throws Exception |
| { |
| doTestSpec(true); |
| } |
| |
| /** |
| * Unit test that verifies that 3 basic keywords (null, true, false) |
| * are properly parsed in various contexts. |
| */ |
| public void testKeywords() |
| throws Exception |
| { |
| final String DOC = "{\n" |
| +"\"key1\" : null,\n" |
| +"\"key2\" : true,\n" |
| +"\"key3\" : false,\n" |
| +"\"key4\" : [ false, null, true ]\n" |
| +"}" |
| ; |
| |
| JsonParser jp = createParserUsingStream(DOC, "UTF-8"); |
| assertToken(JsonToken.START_OBJECT, jp.nextToken()); |
| |
| assertToken(JsonToken.FIELD_NAME, jp.nextToken()); |
| verifyFieldName(jp, "key1"); |
| assertToken(JsonToken.VALUE_NULL, jp.nextToken()); |
| |
| assertToken(JsonToken.FIELD_NAME, jp.nextToken()); |
| verifyFieldName(jp, "key2"); |
| assertToken(JsonToken.VALUE_TRUE, jp.nextToken()); |
| |
| assertToken(JsonToken.FIELD_NAME, jp.nextToken()); |
| verifyFieldName(jp, "key3"); |
| assertToken(JsonToken.VALUE_FALSE, jp.nextToken()); |
| |
| assertToken(JsonToken.FIELD_NAME, jp.nextToken()); |
| verifyFieldName(jp, "key4"); |
| assertToken(JsonToken.START_ARRAY, jp.nextToken()); |
| assertToken(JsonToken.VALUE_FALSE, jp.nextToken()); |
| assertToken(JsonToken.VALUE_NULL, jp.nextToken()); |
| assertToken(JsonToken.VALUE_TRUE, jp.nextToken()); |
| assertToken(JsonToken.END_ARRAY, jp.nextToken()); |
| |
| assertToken(JsonToken.END_OBJECT, jp.nextToken()); |
| } |
| |
| public void testInvalidKeywords() |
| throws Exception |
| { |
| doTestInvalidKeyword1("nul"); |
| doTestInvalidKeyword2("nulla", JsonToken.VALUE_NULL); |
| doTestInvalidKeyword1("fal"); |
| doTestInvalidKeyword3("False"); |
| doTestInvalidKeyword2("falsett0", JsonToken.VALUE_FALSE); |
| doTestInvalidKeyword1("tr"); |
| doTestInvalidKeyword1("truE"); |
| doTestInvalidKeyword2("trueenough", JsonToken.VALUE_TRUE); |
| } |
| |
| /* |
| ///////////////////////////////////////////// |
| // Helper methods |
| ///////////////////////////////////////////// |
| */ |
| |
| private void doTestSpec(boolean verify) |
| throws IOException |
| { |
| // First, using a StringReader: |
| doTestSpecIndividual(null, verify); |
| |
| // Then with streams using supported encodings: |
| doTestSpecIndividual("UTF-8", verify); |
| doTestSpecIndividual("UTF-16BE", verify); |
| doTestSpecIndividual("UTF-16LE", verify); |
| |
| /* Hmmh. UTF-32 is harder only because JDK doesn't come with |
| * a codec for it. Can't test it yet using this method |
| */ |
| //doTestSpecIndividual("UTF-32", verify); |
| } |
| |
| private void doTestSpecIndividual(String enc, boolean verify) |
| throws IOException |
| { |
| String doc = SAMPLE_DOC_JSON_SPEC; |
| JsonParser jp; |
| |
| if (enc == null) { |
| jp = createParserUsingReader(doc); |
| } else { |
| jp = createParserUsingStream(doc, enc); |
| } |
| |
| assertToken(JsonToken.START_OBJECT, jp.nextToken()); // main object |
| |
| assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Image' |
| if (verify) { |
| verifyFieldName(jp, "Image"); |
| } |
| |
| assertToken(JsonToken.START_OBJECT, jp.nextToken()); // 'image' object |
| |
| assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Width' |
| if (verify) { |
| verifyFieldName(jp, "Width"); |
| } |
| |
| assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); |
| if (verify) { |
| verifyIntValue(jp, SAMPLE_SPEC_VALUE_WIDTH); |
| } |
| |
| assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Height' |
| if (verify) { |
| verifyFieldName(jp, "Height"); |
| } |
| |
| assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); |
| verifyIntValue(jp, SAMPLE_SPEC_VALUE_HEIGHT); |
| assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Title' |
| if (verify) { |
| verifyFieldName(jp, "Title"); |
| } |
| assertToken(JsonToken.VALUE_STRING, jp.nextToken()); |
| assertEquals(SAMPLE_SPEC_VALUE_TITLE, getAndVerifyText(jp)); |
| assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Thumbnail' |
| if (verify) { |
| verifyFieldName(jp, "Thumbnail"); |
| } |
| |
| assertToken(JsonToken.START_OBJECT, jp.nextToken()); // 'thumbnail' object |
| assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Url' |
| if (verify) { |
| verifyFieldName(jp, "Url"); |
| } |
| assertToken(JsonToken.VALUE_STRING, jp.nextToken()); |
| if (verify) { |
| assertEquals(SAMPLE_SPEC_VALUE_TN_URL, getAndVerifyText(jp)); |
| } |
| assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Height' |
| if (verify) { |
| verifyFieldName(jp, "Height"); |
| } |
| assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); |
| verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_HEIGHT); |
| assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Width' |
| if (verify) { |
| verifyFieldName(jp, "Width"); |
| } |
| // Width value is actually a String in the example |
| assertToken(JsonToken.VALUE_STRING, jp.nextToken()); |
| assertEquals(SAMPLE_SPEC_VALUE_TN_WIDTH, getAndVerifyText(jp)); |
| |
| assertToken(JsonToken.END_OBJECT, jp.nextToken()); // 'thumbnail' object |
| |
| assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'IDs' |
| assertToken(JsonToken.START_ARRAY, jp.nextToken()); // 'ids' array |
| assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); // ids[0] |
| verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_ID1); |
| assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); // ids[1] |
| verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_ID2); |
| assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); // ids[2] |
| verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_ID3); |
| assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); // ids[3] |
| verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_ID4); |
| assertToken(JsonToken.END_ARRAY, jp.nextToken()); // 'ids' array |
| |
| assertToken(JsonToken.END_OBJECT, jp.nextToken()); // 'image' object |
| |
| assertToken(JsonToken.END_OBJECT, jp.nextToken()); // main object |
| } |
| |
| private void verifyFieldName(JsonParser jp, String expName) |
| throws IOException |
| { |
| assertEquals(expName, jp.getText()); |
| assertEquals(expName, jp.getCurrentName()); |
| } |
| |
| private void verifyIntValue(JsonParser jp, long expValue) |
| throws IOException |
| { |
| // First, via textual |
| assertEquals(String.valueOf(expValue), jp.getText()); |
| } |
| |
| private void doTestInvalidKeyword1(String value) |
| throws IOException |
| { |
| JsonParser jp = createParserUsingStream("{ \"key1\" : "+value+" }", "UTF-8"); |
| assertToken(JsonToken.START_OBJECT, jp.nextToken()); |
| assertToken(JsonToken.FIELD_NAME, jp.nextToken()); |
| try { |
| jp.nextToken(); |
| fail("Expected an exception for malformed value keyword"); |
| } catch (JsonParseException jex) { |
| verifyException(jex, "Unrecognized token"); |
| } |
| } |
| |
| private void doTestInvalidKeyword2(String value, JsonToken firstValue) |
| throws IOException |
| { |
| JsonParser jp = createParserUsingStream("{ \"key1\" : "+value+" }", "UTF-8"); |
| assertToken(JsonToken.START_OBJECT, jp.nextToken()); |
| assertToken(JsonToken.FIELD_NAME, jp.nextToken()); |
| assertToken(firstValue, jp.nextToken()); |
| try { |
| jp.nextToken(); |
| fail("Expected an exception for malformed value keyword"); |
| } catch (JsonParseException jex) { |
| verifyException(jex, "Unexpected character"); |
| } |
| } |
| |
| private void doTestInvalidKeyword3(String value) |
| throws IOException |
| { |
| JsonParser jp = createParserUsingStream("{ \"key1\" : "+value+" }", "UTF-8"); |
| assertToken(JsonToken.START_OBJECT, jp.nextToken()); |
| assertToken(JsonToken.FIELD_NAME, jp.nextToken()); |
| try { |
| jp.nextToken(); |
| fail("Expected an exception for malformed value keyword"); |
| } catch (JsonParseException jex) { |
| verifyException(jex, "expected a valid value"); |
| } |
| } |
| } |
| |