Mercurial > repos > rliterman > csp2
view CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/opt/bbmap-39.01-1/current/json/JsonParser.java @ 68:5028fdace37b
planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author | jpayne |
---|---|
date | Tue, 18 Mar 2025 16:23:26 -0400 |
parents | |
children |
line wrap: on
line source
package json; import java.io.PrintStream; import java.util.ArrayList; import structures.ByteBuilder; /** * How to use this class: * 1) Create one instance per thread * 2) set() some Json text * 3) Call either parseJsonObject or parseJsonArray * @author Brian Bushnell * */ public class JsonParser { /*--------------------------------------------------------------*/ /*---------------- Initialization ----------------*/ /*--------------------------------------------------------------*/ /** For testing */ public static void main(String[] args){ String s; s="{\n" +" \"33154\": {\n" +" \"name\": \"Opisthokonta\",\n" +" \"tax_id\": 33154,\n" +" \"level\": \"no rank\",\n" +" \"no rank\": {\n" +" \"name\": \"Opisthokonta\",\n" +" \"tax_id\": 33154\n" +" },\n" +" \"foo\": {\n" +" \"bar\": \"bam\",\n" +" \"sam\": \"cram\"\n" +" },\n" +" \"foo2\": {\n" +" \"true\": false\n" +" },\n" +" \"foo3\": {\n" +" \"null\": null\n" +" },\n" +" \"foo4\": {\n" +" \"null\": invalid\n" +" },\n" +" \"superkingdom\": {\n" +" \"name\": \"Eukaryota\",\n" +" \"tax_id\": 2759,\n" +" \"number1\": 2759,\n" +" \"number2\": -2759,\n" +" \"number3\": .2759,\n" +" \"number4\": 2.759,\n" +" \"number5\": -2.759,\n" +" \"number6\": -2.759e17,\n" +" \"number7\": -2.759e-1,\n" +" \"number8\": -2.759E-1,\n" +" \"number9\": -2E-1,\n" +" \"slash\": \"hello \\\"world\\\"\",\n" +" \"slash\": \"hello world\",\n" +" \"complex\": [\"hello world\", 1, {\"tax_id\": 2759}, [3, 4, 5]]\n" +" }\n" +" }\n" +"}"; // s="{\"complex\": [\"a\", 1, {\"b\": 2}, [3, 4, 5]]\n}"; System.out.println("Original:\n"+s); JsonParser jp=new JsonParser(s); JsonObject j=jp.parseJsonObject(); System.out.println("Original:\n"+s); System.out.println("Regenerated:\n"+j); s="[\"complex\", 1, {\"b\": 2}, [3, 4, 5]]"; System.out.println("Original:\n"+s); jp.set(s.getBytes()); Object[] array=jp.parseJsonArray(); System.out.println("Original:\n"+s); System.out.println("Regenerated:\n"+JsonObject.toString(array)); } /*--------------------------------------------------------------*/ /*---------------- Initialization ----------------*/ /*--------------------------------------------------------------*/ public JsonParser(){} public JsonParser(String s){ set(s.getBytes()); } public JsonParser(byte[] s){ set(s); } public static JsonObject parseJsonObjectStatic(String s){ return new JsonParser(s).parseJsonObject(); } /*--------------------------------------------------------------*/ /*---------------- Public Methods ----------------*/ /*--------------------------------------------------------------*/ public JsonParser set(byte[] s){ text=s; pos=0; errorState=false; return this; } public JsonObject parseJsonObject(){ if(text==null || text.length<1){return null;} assert(text[0]=='{') : text[0]+"\n"+new String(text); JsonObject o=makeObject(); return o; } public Object[] parseJsonArray(){ if(text==null || text.length<1){return null;} assert(text[0]=='[') : text[0]+"\n"+new String(text); Object[] array=makeArray(); return array; } public boolean validate(){ if(text==null || text.length<1){return true;} try { if(text[0]=='['){ Object[] array=parseJsonArray(); return !errorState; }else if(text[0]=='{'){ JsonObject o=parseJsonObject(); return !errorState; } } catch (Throwable e) {} return false; } /*--------------------------------------------------------------*/ /*---------------- Private Methods ----------------*/ /*--------------------------------------------------------------*/ /** This handles cases when the value is not surrounded by quotes. */ private Object bufferToObject(ByteBuilder bb){ String s=bb.toString(); bb.clear(); final char firstLetter=s.length()>0 ? s.charAt(0) : 0; Object value; try { if(Character.isLetter(firstLetter)){ if(verbose){outstream.println("Letter");} if(s.equalsIgnoreCase("null")){ value=null; }else{ // value=Boolean.parseBoolean(s); value=parseBoolean(s); } }else{ if(verbose){outstream.println("Number");} if(s.indexOf('.')>=0 || s.indexOf('e')>=0 || s.indexOf('E')>=0){ value=Double.parseDouble(s); }else{ value=Long.parseLong(s); } } } catch (Exception e) { //This handles an incorrectly formatted input file errorState=true; value=s; } return value; } /** Not strictly correct, but allows t and f */ private static boolean parseBoolean(String s) throws Exception{ if(s==null){throw INVALID_JSON;} if(s.equalsIgnoreCase("true") || s.equalsIgnoreCase("t")){return true;} if(s.equalsIgnoreCase("false") || s.equalsIgnoreCase("f")){return false;} throw INVALID_JSON; } /** Create a JsonObject from { to the next } */ private JsonObject makeObject(){ assert(text[pos]=='{'); pos++; if(verbose){outstream.println("Entering makeObject.");} JsonObject current=new JsonObject(); ByteBuilder bb=new ByteBuilder(); boolean quoteMode=false; boolean slashMode=false; String key=null; for(; pos<text.length; pos++){ final byte b=text[pos]; // if(verbose){outstream.println(pos+"=\t"+(char)b); if(quoteMode){ if(slashMode){ if(verbose){outstream.println(">SlashModeEnd, buffer="+bb);} bb.append(b); slashMode=false; }else if(b=='"'){ if(verbose){outstream.println(">Quote; quote mode="+quoteMode+", key="+key+", buffer="+bb);} String s=bb.toString(); bb.clear(); if(key==null){ key=s; if(verbose){outstream.println("Set key to \""+key+"\"");} }else{ current.add(key, s); if(verbose){outstream.println("Added \""+key+"\": \""+s+"\"");} key=null; } quoteMode=!quoteMode; }else{ if(verbose){outstream.println(">QuoteMode, buffer="+bb);} if(b=='\\'){ if(verbose){outstream.println(">SlashMode, buffer="+bb);} slashMode=true; } bb.append(b); } }else if(b=='"'){ if(verbose){outstream.println(">Quote; quote mode="+quoteMode+", key="+key+", buffer="+bb);} quoteMode=!quoteMode; }else if(b==','){ if(verbose){outstream.println(">Comma; key="+key+", buffer=\""+bb+"\""/*+"\n"+new String(text, 0, pos)*/);} if(key!=null){//number or boolean final Object value=bufferToObject(bb); current.add(key, value); key=null; if(verbose){outstream.println("Added "+value+"; current=\n"+current+"\n");} } }else if(b==':'){ if(verbose){outstream.println(">Colon");} assert(key!=null); }else if(b=='{'){ if(verbose){outstream.println(">{, key="+key+", A) current object is:\n"+current+"\n");} JsonObject j=makeObject(); if(key==null){//outermost? if(verbose){outstream.println("Returning.");} return j; }else{ current.add(key, j); if(verbose){outstream.println("Added new object:\n"+j+"\n");} key=null; } }else if(b=='}'){ if(verbose){outstream.println(">}, key="+key+", B) current object is:\n"+current+"\n");} if(key!=null){//number or boolean final Object value=bufferToObject(bb); current.add(key, value); key=null; if(verbose){outstream.println("Added "+value+"; current=\n"+current+"\n");} } pos++; return current; }else if(b=='['){ if(verbose){outstream.println(">[, C) current object is:\n"+current+"\n");} Object[] array=makeArray(); assert(key!=null) : "Should be in makeArray."; current.add(key, array); key=null; assert(bb.length()==0); }else if(b==']'){ if(verbose){outstream.println(">], D) current object is:\n"+current+"\n");} assert(false); }else if(b==' ' || b=='\t' || b=='\n' || b=='\r'){ if(verbose){outstream.println(">Other");} //ignore }else{ if(verbose){outstream.println(">NormalMode, buffer="+bb);} bb.append(b); } } return current; } /** Create an array from [ to the next ] */ private Object[] makeArray(){ assert(text[pos]=='['); pos++; if(verbose){outstream.println("Entering makeArray.");} ArrayList<Object> current=new ArrayList<Object>(); ByteBuilder bb=new ByteBuilder(); boolean quoteMode=false; boolean slashMode=false; for(; pos<text.length; pos++){ final byte b=text[pos]; if(quoteMode){ if(slashMode){ if(verbose){outstream.println(">SlashModeEnd, buffer="+bb);} bb.append(b); slashMode=false; }else if(b=='"'){ if(verbose){outstream.println(">Quote; quote mode="+quoteMode+", buffer="+bb);} String s=bb.toString(); bb.clear(); current.add(s); quoteMode=!quoteMode; }else{ if(verbose){outstream.println(">QuoteMode, buffer="+bb);} if(b=='\\'){ if(verbose){outstream.println(">SlashMode, buffer="+bb);} slashMode=true; } bb.append(b); } }else if(b=='"'){ if(verbose){outstream.println(">Quote; quote mode="+quoteMode+", buffer="+bb);} quoteMode=!quoteMode; }else if(b==','){ if(verbose){outstream.println(">Comma; buffer=\""+bb+"\"");} if(bb.length()>0){ final Object value=bufferToObject(bb); current.add(value); if(verbose){outstream.println("Added "+value+"; current=\n"+current+"\n");} } }else if(b==':'){ if(verbose){outstream.println(">Colon");} assert(false); }else if(b=='{'){ if(verbose){outstream.println(">{, E) current object is:\n"+current+"\n");} JsonObject j=makeObject(); current.add(j); if(verbose){outstream.println("Added new object:\n"+j+"\n");} }else if(b=='}'){ if(verbose){outstream.println(">}, current array is:\n"+current+"\n");} assert(false); }else if(b=='['){ if(verbose){outstream.println(">[, F) current object is:\n"+current+"\n");} Object[] array=makeArray(); current.add(array); }else if(b==']'){ if(verbose){outstream.println(">], G) current object is:\n"+current+"\n");} if(bb.length()>0){ final Object value=bufferToObject(bb); current.add(value); if(verbose){outstream.println("Added "+value+"; current=\n"+current+"\n");} } if(verbose){outstream.println("Returning "+current+"; text="+new String(text, 0, pos));} return current.toArray(); }else if(b==' ' || b=='\t' || b=='\n' || b=='\r'){ if(verbose){outstream.println(">Other");} //ignore }else{ if(verbose){outstream.println(">NormalMode, buffer="+bb);} bb.append(b); } } return current.toArray(); } /*--------------------------------------------------------------*/ /*---------------- Fields ----------------*/ /*--------------------------------------------------------------*/ byte[] text; int pos=0; boolean errorState; /** Always false except when testing */ private static final boolean verbose=false; private static final PrintStream outstream=System.err; private static final Exception INVALID_JSON=new Exception("Invalid Json"); }