package javaforce; /** JSON parser (JavaScript Object Notation) Does NOT Support multi-dimension arrays. */ import java.util.*; /* example: { "key": "value", "key2" : ["v1", "v2"], "key3" : { "key" : "value", "etc" : "value" } "key4" : [ "v1", "v2" ] } */ public class JSON { public static class Element { public String key; public String value; public ArrayList<Element> children = new ArrayList<Element>(); } /** Parses a JSON string. */ public static Element parse(String str) throws Exception { Element root = new Element(); root.key = "root"; parseElement(root, str.trim()); return root; } /* reads key : returns str left over */ private static String readKey(Element e, String str) throws Exception { boolean quote = false; int pos = 0; e.key = ""; while (true) { char ch = str.charAt(pos++); if (ch == '\"') { if (quote) { quote = false; } else { if (e.key.length() > 0) throw new Exception("bad key name"); quote = true; } continue; } if (quote) { e.key += ch; } else { switch (ch) { case ' ': case '\r': case '\n': case '\t': case ',': if (e.key.length() > 0) return str.substring(pos); break; case '}': return str.substring(pos-1); case ':': if (e.key.length() == 0) throw new Exception("no key name"); return str.substring(pos); case '{': case '[': case ']': throw new Exception("bad key name:" + ch); default: e.key += ch; } } } } private static String readArray(Element e, String key, String str) throws Exception { while (true) { Element child = new Element(); child.key = key; //repeat key for each array element str = readValue(child, str, true); if ((child.value.length() > 0) || (child.children.size() > 0)) { // JFLog.log(child.key + "=" + child.value); e.children.add(child); } if (str.startsWith("]")) return str.substring(1); } } /* reads value : returns str left over */ private static String readValue(Element e, String str, boolean array) throws Exception { boolean quote = false, escape = false; int pos = 0; e.value = ""; while (true) { char ch = str.charAt(pos++); if ((ch == '\"') && (!escape)) { if (quote) { return str.substring(pos); } else { if (e.value.length() > 0) throw new Exception("bad value"); quote = true; } continue; } if ((ch == '\\') && (!escape)) { escape = true; } if (quote) { if (escape) { switch (ch) { case 'n': e.value += "\n"; break; case 'r': e.value += "\r"; break; case 't': e.value += "\t"; break; case 'b': e.value += "\b"; break; case 'f': e.value += "\f"; break; default: e.value += ch; break; } escape = false; } else { e.value += ch; } } else { switch (ch) { case ' ': case '\r': case '\n': case '\t': case ',': if (e.value.length() > 0) { return str.substring(pos); } break; case ':': if (e.value.length() > 0) throw new Exception("bad value"); break; case '{': if (e.value.length() > 0) throw new Exception("bad value"); return parseElement(e, str.substring(pos-1)); case '}': if (e.value.length() > 0) { return str.substring(pos); } throw new Exception("bad value"); case '[': if (e.value.length() > 0) throw new Exception("bad value"); return str.substring(pos-1); case ']': if (!array) throw new Exception("bad array"); return str.substring(pos-1); default: if (escape) { switch (ch) { case 'n': e.value += "\n"; break; case 'r': e.value += "\r"; break; case 't': e.value += "\t"; break; case 'b': e.value += "\b"; break; case 'f': e.value += "\f"; break; default: e.value += ch; break; } escape = false; } else { e.value += ch; } } } } } private static String readOpen(String str) throws Exception { int pos = 0; while (true) { char ch = str.charAt(pos++); switch (ch) { case '{': return str.substring(pos); case ' ': case 9: continue; } throw new Exception("bad json string"); } } private static String parseElement(Element e, String str) throws Exception { //str = { ... } str = readOpen(str); while (str.length() > 0) { Element child = new Element(); str = readKey(child, str); if (str.startsWith("}")) return str.substring(1); str = readValue(child, str, false); if (str.startsWith("[")) { str = readArray(e, child.key, str.substring(1)); continue; } // JFLog.log(child.key + "=" + child.value); e.children.add(child); } return str; } public static XML toXML(Element e) { XML xml = new XML(); xml.root.setName(e.key); xml.root.setContent(e.value); addXML(e, xml, xml.root); return xml; } private static void addXML(Element e, XML xml, XML.XMLTag tag) { for(int a=0;a<e.children.size();a++) { Element c = e.children.get(a); XML.XMLTag child = xml.addTag(tag, c.key, "", c.value); addXML(c, xml, child); } } }