From b8a2897cc40e82f759b0b20d6f20edc68088c956 Mon Sep 17 00:00:00 2001 From: Noble Paul Date: Sun, 18 Sep 2016 19:55:41 +0530 Subject: [PATCH 1/2] noggit-7: Make starting and ending braces optional --- src/main/java/org/noggit/JSONParser.java | 20 ++++++++++++++++--- src/test/java/org/noggit/TestJSONParser.java | 11 ++++++++-- .../java/org/noggit/TestObjectBuilder.java | 8 ++++++++ 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/noggit/JSONParser.java b/src/main/java/org/noggit/JSONParser.java index acafd83..2a13bcd 100755 --- a/src/main/java/org/noggit/JSONParser.java +++ b/src/main/java/org/noggit/JSONParser.java @@ -71,6 +71,7 @@ public class JSONParser { */ public static final int ALLOW_EXTRA_COMMAS = 1 << 5; public static final int ALLOW_MISSING_COLON_COMMA_BEFORE_OBJECT = 1 << 6; + public static final int OPTIONAL_OUTER_BRACES = 1 << 7; public static final int FLAGS_STRICT = 0; public static final int FLAGS_DEFAULT = ALLOW_COMMENTS | ALLOW_SINGLE_QUOTES | ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER | ALLOW_UNQUOTED_KEYS | ALLOW_UNQUOTED_STRING_VALUES | ALLOW_EXTRA_COMMAS; @@ -115,6 +116,8 @@ public static String getEventString( int e ) protected int stringTerm; // The terminator for the last string we read: single quote, double quote, or 0 for unterminated. + protected boolean missingOpeningBrace = false; + public JSONParser(Reader in) { this(in, new char[8192]); // 8192 matches the default buffer size of a BufferedReader so double @@ -1020,7 +1023,15 @@ public int nextEvent() throws IOException { outer: for(;;) { switch (state) { case 0: - return event = next(getChar()); + event = next(getChar()); + if (event == STRING && (flags & OPTIONAL_OUTER_BRACES) != 0) { + if (start > 0) start--; + missingOpeningBrace = true; + stringTerm = 0; + valstate = 0; + event = next('{'); + } + return event; case DID_OBJSTART: ch = getCharExpected('"'); if (ch == '}') { @@ -1056,8 +1067,11 @@ public int nextEvent() throws IOException { } else if (ch != ',') { if ((flags & ALLOW_EXTRA_COMMAS) != 0 && (ch == '\'' || ch == '"' || Character.isLetter(ch))) { start--; - } else - throw err("Expected ',' or '}'"); + } else if (missingOpeningBrace && ch == -1 && (flags & OPTIONAL_OUTER_BRACES) != 0) { + missingOpeningBrace = false; + pop(); + return event = OBJECT_END; + } else throw err("Expected ',' or '}'"); } ch = getCharExpected('"'); if (ch == '"') { diff --git a/src/test/java/org/noggit/TestJSONParser.java b/src/test/java/org/noggit/TestJSONParser.java index 2b1d715..9410546 100755 --- a/src/test/java/org/noggit/TestJSONParser.java +++ b/src/test/java/org/noggit/TestJSONParser.java @@ -18,6 +18,7 @@ import java.io.IOException; import java.io.StringReader; +import java.util.Map; import java.util.Random; import junit.framework.TestCase; @@ -41,7 +42,7 @@ public class TestJSONParser extends TestCase { public static String lastParser() { return "parserType=" + parserType + (parserType==1 ? " bufferSize=" + bufferSize : "") - + " parserInput='" + parserInput + "'"; + + " parserInput='" + parserInput + "'" + "flags : " + lastParser.flags; } public static JSONParser getParser(String s) { @@ -314,7 +315,6 @@ public static void parse(String input, boolean changeSingleQuote, Object[] expec } - public static void err(String input) throws IOException { try { JSONParser p = getParser(input); @@ -624,6 +624,13 @@ public void testObject() throws IOException { parse("{'a':[['b']['c']]}", new Object[]{m, "a", a, a, "b", A, a, "c", A, A, M, e}); parse("{'a': {'b':'c'} 'd': {'e':'f'}}", new Object[]{m, "a", m, "b", "c",M, "d", m,"e","f", M, M, e}); parse("{'a': {'b':'c'} d: {'e':'f'}}", new Object[]{m, "a", m, "b", "c",M, "d", m,"e","f", M, M, e}); + + flags = JSONParser.FLAGS_DEFAULT | JSONParser.ALLOW_MISSING_COLON_COMMA_BEFORE_OBJECT | JSONParser.OPTIONAL_OUTER_BRACES; + parse("'a':{'b':'c'}", new Object[]{m, "a", m, "b", "c", M, M, e}); + parse("'a':{'b':'c'}", true, new Object[]{m, "a", m, "b", "c", M, M, e}); + parse("a:'b'", new Object[]{m, "a", "b", M, e}); + + flags = JSONParser.FLAGS_DEFAULT; } diff --git a/src/test/java/org/noggit/TestObjectBuilder.java b/src/test/java/org/noggit/TestObjectBuilder.java index ffc5ecb..c67ba3d 100644 --- a/src/test/java/org/noggit/TestObjectBuilder.java +++ b/src/test/java/org/noggit/TestObjectBuilder.java @@ -55,6 +55,14 @@ public static Map O(Object... lst) { } return map; } + public void testWithoutStartingBraces() throws IOException { + JSONParser parser = new JSONParser("a: {key:val1}b:{key:val2}"); + parser.setFlags(JSONParser.FLAGS_DEFAULT | JSONParser.OPTIONAL_OUTER_BRACES| JSONParser.ALLOW_MISSING_COLON_COMMA_BEFORE_OBJECT); + ObjectBuilder objectBuilder = new ObjectBuilder(parser); + String s1 = JSONUtil.toJSON(objectBuilder.getObject(),-1); + String expected = JSONUtil.toJSON(O("a", O("key", "val1"), "b", O("key", "val2")),-1); + assertEquals(s1, expected); + } public void testVariations(String str, Object expected) throws IOException { test("["+str+"]", L(expected)); From f40edc05632e6b79dd0830cf2b249aee33ae83fa Mon Sep 17 00:00:00 2001 From: Noble Paul Date: Sat, 21 Oct 2017 17:47:35 +1030 Subject: [PATCH 2/2] noggit-21: Port the MapWriter, IteratorWriter equivalent interfaces from SolrJ to noggit --- pom.xml | 4 +- src/main/java/org/noggit/IteratorWriter.java | 64 ++++++++++++++++ src/main/java/org/noggit/MapWriter.java | 78 ++++++++++++++++++++ 3 files changed, 144 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/noggit/IteratorWriter.java create mode 100644 src/main/java/org/noggit/MapWriter.java diff --git a/pom.xml b/pom.xml index c6c2c77..c5bbda5 100755 --- a/pom.xml +++ b/pom.xml @@ -58,8 +58,8 @@ maven-compiler-plugin 3.1 - 1.5 - 1.5 + 1.8 + 1.8 diff --git a/src/main/java/org/noggit/IteratorWriter.java b/src/main/java/org/noggit/IteratorWriter.java new file mode 100644 index 0000000..9f1634f --- /dev/null +++ b/src/main/java/org/noggit/IteratorWriter.java @@ -0,0 +1,64 @@ +/** + * Copyright 2006- Yonik Seeley + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.noggit; + +import java.io.IOException; + +/** + * Interface to help do push writing to an array + */ +public interface IteratorWriter { + /** + * @param iw after this method returns , the ItemWriter Object is invalid + * Do not hold a reference to this object + */ + void writeIter(ItemWriter iw) throws IOException; + + interface ItemWriter { + /** + * The item could be any supported type + */ + ItemWriter add(Object o) throws IOException; + + default ItemWriter add(int v) throws IOException { + add((Integer) v); + return this; + } + + + default ItemWriter add(long v) throws IOException { + add((Long) v); + return this; + } + + + default ItemWriter add(float v) throws IOException { + add((Float) v); + return this; + } + + default ItemWriter add(double v) throws IOException { + add((Double) v); + return this; + } + + default ItemWriter add(boolean v) throws IOException { + add((Boolean) v); + return this; + } + } + +} diff --git a/src/main/java/org/noggit/MapWriter.java b/src/main/java/org/noggit/MapWriter.java new file mode 100644 index 0000000..42ef032 --- /dev/null +++ b/src/main/java/org/noggit/MapWriter.java @@ -0,0 +1,78 @@ +package org.noggit; + +/** + * Copyright 2006- Yonik Seeley + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import java.io.IOException; + +/** + * Use this class to push all entries of a Map into an output. + * This avoids creating map instances and is supposed to be memory efficient. + * If the entries are primitives, unnecessary boxing is also avoided + */ +public interface MapWriter { + + + + void writeMap(EntryWriter ew) throws IOException; + + /** + * An interface to push one entry at a time to the output + */ + interface EntryWriter { + + /** + * Writes a key value into the map + * + * @param k The key + * @param v The value can be any supported object + */ + EntryWriter put(String k, Object v) throws IOException; + + default EntryWriter putIfNotNull(String k, Object v) throws IOException { + if(v != null) put(k,v); + return this; + } + + + default EntryWriter put(String k, int v) throws IOException { + put(k, (Integer) v); + return this; + } + + + default EntryWriter put(String k, long v) throws IOException { + put(k, (Long) v); + return this; + } + + + default EntryWriter put(String k, float v) throws IOException { + put(k, (Float) v); + return this; + } + + default EntryWriter put(String k, double v) throws IOException { + put(k, (Double) v); + return this; + } + + default EntryWriter put(String k, boolean v) throws IOException { + put(k, (Boolean) v); + return this; + } + } +}