/** * Parse JSON text into java object from the input source. * * @param in * @param containerFactory - Use this factory to createyour own JSON object and JSON array * containers. * @return Instance of the following: org.json.simple.JSONObject, org.json.simple.JSONArray, * java.lang.String, java.lang.Number, java.lang.Boolean, null * @throws IOException * @throws ParseException */ public Object parse(Reader in, ContainerFactory containerFactory) throws IOException, ParseException { reset(in); LinkedList statusStack = new LinkedList(); LinkedList valueStack = new LinkedList(); try { do { nextToken(); switch (status) { case S_INIT: switch (token.type) { case Yytoken.TYPE_VALUE: status = S_IN_FINISHED_VALUE; statusStack.addFirst(new Integer(status)); valueStack.addFirst(token.value); break; case Yytoken.TYPE_LEFT_BRACE: status = S_IN_OBJECT; statusStack.addFirst(new Integer(status)); valueStack.addFirst(createObjectContainer(containerFactory)); break; case Yytoken.TYPE_LEFT_SQUARE: status = S_IN_ARRAY; statusStack.addFirst(new Integer(status)); valueStack.addFirst(createArrayContainer(containerFactory)); break; default: status = S_IN_ERROR; // inner switch } break; case S_IN_FINISHED_VALUE: if (token.type == Yytoken.TYPE_EOF) return valueStack.removeFirst(); else throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); case S_IN_OBJECT: switch (token.type) { case Yytoken.TYPE_COMMA: break; case Yytoken.TYPE_VALUE: if (token.value instanceof String) { String key = (String) token.value; valueStack.addFirst(key); status = S_PASSED_PAIR_KEY; statusStack.addFirst(new Integer(status)); } else { status = S_IN_ERROR; } break; case Yytoken.TYPE_RIGHT_BRACE: if (valueStack.size() > 1) { statusStack.removeFirst(); valueStack.removeFirst(); status = peekStatus(statusStack); } else { status = S_IN_FINISHED_VALUE; } break; default: status = S_IN_ERROR; break; // inner switch } break; case S_PASSED_PAIR_KEY: switch (token.type) { case Yytoken.TYPE_COLON: break; case Yytoken.TYPE_VALUE: statusStack.removeFirst(); String key = (String) valueStack.removeFirst(); Map parent = (Map) valueStack.getFirst(); parent.put(key, token.value); status = peekStatus(statusStack); break; case Yytoken.TYPE_LEFT_SQUARE: statusStack.removeFirst(); key = (String) valueStack.removeFirst(); parent = (Map) valueStack.getFirst(); List newArray = createArrayContainer(containerFactory); parent.put(key, newArray); status = S_IN_ARRAY; statusStack.addFirst(new Integer(status)); valueStack.addFirst(newArray); break; case Yytoken.TYPE_LEFT_BRACE: statusStack.removeFirst(); key = (String) valueStack.removeFirst(); parent = (Map) valueStack.getFirst(); Map newObject = createObjectContainer(containerFactory); parent.put(key, newObject); status = S_IN_OBJECT; statusStack.addFirst(new Integer(status)); valueStack.addFirst(newObject); break; default: status = S_IN_ERROR; } break; case S_IN_ARRAY: switch (token.type) { case Yytoken.TYPE_COMMA: break; case Yytoken.TYPE_VALUE: List val = (List) valueStack.getFirst(); val.add(token.value); break; case Yytoken.TYPE_RIGHT_SQUARE: if (valueStack.size() > 1) { statusStack.removeFirst(); valueStack.removeFirst(); status = peekStatus(statusStack); } else { status = S_IN_FINISHED_VALUE; } break; case Yytoken.TYPE_LEFT_BRACE: val = (List) valueStack.getFirst(); Map newObject = createObjectContainer(containerFactory); val.add(newObject); status = S_IN_OBJECT; statusStack.addFirst(new Integer(status)); valueStack.addFirst(newObject); break; case Yytoken.TYPE_LEFT_SQUARE: val = (List) valueStack.getFirst(); List newArray = createArrayContainer(containerFactory); val.add(newArray); status = S_IN_ARRAY; statusStack.addFirst(new Integer(status)); valueStack.addFirst(newArray); break; default: status = S_IN_ERROR; // inner switch } break; case S_IN_ERROR: throw new ParseException( getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); // switch } if (status == S_IN_ERROR) { throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); } } while (token.type != Yytoken.TYPE_EOF); } catch (IOException ie) { throw ie; } throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); }
/** * Stream processing of JSON text. * * @see ContentHandler * @param in * @param contentHandler * @param isResume - Indicates if it continues previous parsing operation. If set to true, resume * parsing the old stream, and parameter 'in' will be ignored. If this method is called for * the first time in this instance, isResume will be ignored. * @throws IOException * @throws ParseException */ public void parse(Reader in, ContentHandler contentHandler, boolean isResume) throws IOException, ParseException { if (!isResume) { reset(in); handlerStatusStack = new LinkedList(); } else { if (handlerStatusStack == null) { isResume = false; reset(in); handlerStatusStack = new LinkedList(); } } LinkedList statusStack = handlerStatusStack; try { do { switch (status) { case S_INIT: contentHandler.startJSON(); nextToken(); switch (token.type) { case Yytoken.TYPE_VALUE: status = S_IN_FINISHED_VALUE; statusStack.addFirst(new Integer(status)); if (!contentHandler.primitive(token.value)) return; break; case Yytoken.TYPE_LEFT_BRACE: status = S_IN_OBJECT; statusStack.addFirst(new Integer(status)); if (!contentHandler.startObject()) return; break; case Yytoken.TYPE_LEFT_SQUARE: status = S_IN_ARRAY; statusStack.addFirst(new Integer(status)); if (!contentHandler.startArray()) return; break; default: status = S_IN_ERROR; // inner switch } break; case S_IN_FINISHED_VALUE: nextToken(); if (token.type == Yytoken.TYPE_EOF) { contentHandler.endJSON(); status = S_END; return; } else { status = S_IN_ERROR; throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); } case S_IN_OBJECT: nextToken(); switch (token.type) { case Yytoken.TYPE_COMMA: break; case Yytoken.TYPE_VALUE: if (token.value instanceof String) { String key = (String) token.value; status = S_PASSED_PAIR_KEY; statusStack.addFirst(new Integer(status)); if (!contentHandler.startObjectEntry(key)) return; } else { status = S_IN_ERROR; } break; case Yytoken.TYPE_RIGHT_BRACE: if (statusStack.size() > 1) { statusStack.removeFirst(); status = peekStatus(statusStack); } else { status = S_IN_FINISHED_VALUE; } if (!contentHandler.endObject()) return; break; default: status = S_IN_ERROR; break; // inner switch } break; case S_PASSED_PAIR_KEY: nextToken(); switch (token.type) { case Yytoken.TYPE_COLON: break; case Yytoken.TYPE_VALUE: statusStack.removeFirst(); status = peekStatus(statusStack); if (!contentHandler.primitive(token.value)) return; if (!contentHandler.endObjectEntry()) return; break; case Yytoken.TYPE_LEFT_SQUARE: statusStack.removeFirst(); statusStack.addFirst(new Integer(S_IN_PAIR_VALUE)); status = S_IN_ARRAY; statusStack.addFirst(new Integer(status)); if (!contentHandler.startArray()) return; break; case Yytoken.TYPE_LEFT_BRACE: statusStack.removeFirst(); statusStack.addFirst(new Integer(S_IN_PAIR_VALUE)); status = S_IN_OBJECT; statusStack.addFirst(new Integer(status)); if (!contentHandler.startObject()) return; break; default: status = S_IN_ERROR; } break; case S_IN_PAIR_VALUE: statusStack.removeFirst(); status = peekStatus(statusStack); if (!contentHandler.endObjectEntry()) return; break; /* * S_IN_PAIR_VALUE is just a marker to indicate the end of an object entry, it doesn't proccess any token, * therefore delay consuming token until next round. */ case S_IN_ARRAY: nextToken(); switch (token.type) { case Yytoken.TYPE_COMMA: break; case Yytoken.TYPE_VALUE: if (!contentHandler.primitive(token.value)) return; break; case Yytoken.TYPE_RIGHT_SQUARE: if (statusStack.size() > 1) { statusStack.removeFirst(); status = peekStatus(statusStack); } else { status = S_IN_FINISHED_VALUE; } if (!contentHandler.endArray()) return; break; case Yytoken.TYPE_LEFT_BRACE: status = S_IN_OBJECT; statusStack.addFirst(new Integer(status)); if (!contentHandler.startObject()) return; break; case Yytoken.TYPE_LEFT_SQUARE: status = S_IN_ARRAY; statusStack.addFirst(new Integer(status)); if (!contentHandler.startArray()) return; break; default: status = S_IN_ERROR; // inner switch } break; case S_END: return; case S_IN_ERROR: throw new ParseException( getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); // switch } if (status == S_IN_ERROR) { throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); } } while (token.type != Yytoken.TYPE_EOF); } catch (IOException ie) { status = S_IN_ERROR; throw ie; } catch (ParseException pe) { status = S_IN_ERROR; throw pe; } catch (RuntimeException re) { status = S_IN_ERROR; throw re; } catch (Error e) { status = S_IN_ERROR; throw e; } status = S_IN_ERROR; throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); }
/** * Reset the parser to the initial state with a new character reader. * * @param in - The new character reader. * @throws IOException * @throws ParseException */ public void reset(Reader in) { lexer.yyreset(in); reset(); }
@SuppressWarnings("unchecked") public void testDecode() throws Exception { System.out.println("=======decode======="); String s = "[0,{\"1\":{\"2\":{\"3\":{\"4\":[5,{\"6\":7}]}}}}]"; Object obj = JSONValue.parse(s); JSONArray array = (JSONArray) obj; System.out.println("======the 2nd element of array======"); System.out.println(array.get(1)); System.out.println(); assertEquals("{\"1\":{\"2\":{\"3\":{\"4\":[5,{\"6\":7}]}}}}", array.get(1).toString()); JSONObject obj2 = (JSONObject) array.get(1); System.out.println("======field \"1\"=========="); System.out.println(obj2.get("1")); assertEquals("{\"2\":{\"3\":{\"4\":[5,{\"6\":7}]}}}", obj2.get("1").toString()); s = "{}"; obj = JSONValue.parse(s); assertEquals("{}", obj.toString()); s = "[5,]"; obj = JSONValue.parse(s); assertEquals("[5]", obj.toString()); s = "[5,,2]"; obj = JSONValue.parse(s); assertEquals("[5,2]", obj.toString()); s = "[\"hello\\bworld\\\"abc\\tdef\\\\ghi\\rjkl\\n123\\u4e2d\"]"; obj = JSONValue.parse(s); assertEquals("hello\bworld\"abc\tdef\\ghi\rjkl\n123δΈ", ((List<Object>) obj).get(0).toString()); JSONParser parser = new JSONParser(); s = "{\"name\":"; try { obj = parser.parse(s); } catch (ParseException pe) { assertEquals(ParseException.ERROR_UNEXPECTED_TOKEN, pe.getErrorType()); assertEquals(8, pe.getPosition()); } s = "{\"name\":}"; try { obj = parser.parse(s); } catch (ParseException pe) { assertEquals(ParseException.ERROR_UNEXPECTED_TOKEN, pe.getErrorType()); assertEquals(8, pe.getPosition()); } s = "{\"name"; try { obj = parser.parse(s); } catch (ParseException pe) { assertEquals(ParseException.ERROR_UNEXPECTED_TOKEN, pe.getErrorType()); assertEquals(6, pe.getPosition()); } s = "[[null, 123.45, \"a\\\tb c\"}, true]"; try { parser.parse(s); } catch (ParseException pe) { assertEquals(24, pe.getPosition()); System.out.println("Error at character position: " + pe.getPosition()); switch (pe.getErrorType()) { case ParseException.ERROR_UNEXPECTED_TOKEN: System.out.println("Unexpected token: " + pe.getUnexpectedObject()); break; case ParseException.ERROR_UNEXPECTED_CHAR: System.out.println("Unexpected character: " + pe.getUnexpectedObject()); break; case ParseException.ERROR_UNEXPECTED_EXCEPTION: ((Exception) pe.getUnexpectedObject()).printStackTrace(); break; } } s = "{\"first\": 123, \"second\": [4, 5, 6], \"third\": 789}"; ContainerFactory containerFactory = new ContainerFactory() { public List<Object> creatArrayContainer() { return new LinkedList<Object>(); } public Map<Object, Object> createObjectContainer() { return new LinkedHashMap<Object, Object>(); } }; try { Map<Object, Object> json = (Map<Object, Object>) parser.parse(s, containerFactory); Iterator<Map.Entry<Object, Object>> iter = json.entrySet().iterator(); System.out.println("==iterate result=="); while (iter.hasNext()) { Map.Entry<Object, Object> entry = (Map.Entry<Object, Object>) iter.next(); System.out.println(entry.getKey() + "=>" + entry.getValue()); } System.out.println("==toJSONString()=="); System.out.println(JSONValue.toJSONString(json)); assertEquals( "{\"first\":123,\"second\":[4,5,6],\"third\":789}", JSONValue.toJSONString(json)); } catch (ParseException pe) { pe.printStackTrace(); } s = "{\"first\": 123, \"second\": [{\"s1\":{\"s11\":\"v11\"}}, 4, 5, 6], \"third\": 789}"; ContentHandler myHandler = new ContentHandler() { public boolean endArray() throws ParseException { System.out.println("endArray()"); return true; } public void endJSON() throws ParseException { System.out.println("endJSON()"); } public boolean endObject() throws ParseException { System.out.println("endObject()"); return true; } public boolean endObjectEntry() throws ParseException { System.out.println("endObjectEntry()"); return true; } public boolean primitive(Object value) throws ParseException { System.out.println("primitive(): " + value); return true; } public boolean startArray() throws ParseException { System.out.println("startArray()"); return true; } public void startJSON() throws ParseException { System.out.println("startJSON()"); } public boolean startObject() throws ParseException { System.out.println("startObject()"); return true; } public boolean startObjectEntry(String key) throws ParseException { System.out.println("startObjectEntry(), key:" + key); return true; } }; try { parser.parse(s, myHandler); } catch (ParseException pe) { pe.printStackTrace(); } class KeyFinder implements ContentHandler { private Object value; private boolean found = false; private boolean end = false; private String key; private String matchKey; public void setMatchKey(String matchKey) { this.matchKey = matchKey; } public Object getValue() { return value; } public boolean isEnd() { return end; } public void setFound(boolean found) { this.found = found; } public boolean isFound() { return found; } public void startJSON() throws ParseException, IOException { found = false; end = false; } public void endJSON() throws ParseException, IOException { end = true; } public boolean primitive(Object value) throws ParseException, IOException { if (key != null) { if (key.equals(matchKey)) { found = true; this.value = value; key = null; return false; } } return true; } public boolean startArray() throws ParseException, IOException { return true; } public boolean startObject() throws ParseException, IOException { return true; } public boolean startObjectEntry(String key) throws ParseException, IOException { this.key = key; return true; } public boolean endArray() throws ParseException, IOException { return false; } public boolean endObject() throws ParseException, IOException { return true; } public boolean endObjectEntry() throws ParseException, IOException { return true; } }; s = "{\"first\": 123, \"second\": [{\"k1\":{\"id\":\"id1\"}}, 4, 5, 6, {\"id\": 123}], \"third\": 789, \"id\": null}"; parser.reset(); KeyFinder keyFinder = new KeyFinder(); keyFinder.setMatchKey("id"); int i = 0; try { while (!keyFinder.isEnd()) { parser.parse(s, keyFinder, true); if (keyFinder.isFound()) { i++; keyFinder.setFound(false); System.out.println("found id:"); System.out.println(keyFinder.getValue()); if (i == 1) assertEquals("id1", keyFinder.getValue()); if (i == 2) { assertTrue(keyFinder.getValue() instanceof Number); assertEquals("123", String.valueOf(keyFinder.getValue())); } if (i == 3) assertTrue(null == keyFinder.getValue()); } } } catch (ParseException pe) { pe.printStackTrace(); } }