Friday, December 2, 2011

svn commit: r1209632 - in /labs/noggit/src: main/java/org/apache/noggit/ test/java/org/apache/noggit/

Author: yonik
Date: Fri Dec 2 18:48:42 2011
New Revision: 1209632

URL: http://svn.apache.org/viewvc?rev=1209632&view=rev
Log:
noggit: refactor JSONWriter, add indenting, change string escaping to avoid illegal javascript chars

Added:
labs/noggit/src/main/java/org/apache/noggit/JSONWriter.java
- copied, changed from r1099567, labs/noggit/src/main/java/org/apache/noggit/TextWriter.java
labs/noggit/src/test/java/org/apache/noggit/TestJSONWriter.java (with props)
Removed:
labs/noggit/src/main/java/org/apache/noggit/TextWriter.java
Modified:
labs/noggit/src/main/java/org/apache/noggit/JSONUtil.java
labs/noggit/src/test/java/org/apache/noggit/TestObjectBuilder.java

Modified: labs/noggit/src/main/java/org/apache/noggit/JSONUtil.java
URL: http://svn.apache.org/viewvc/labs/noggit/src/main/java/org/apache/noggit/JSONUtil.java?rev=1209632&r1=1209631&r2=1209632&view=diff
==============================================================================
--- labs/noggit/src/main/java/org/apache/noggit/JSONUtil.java (original)
+++ labs/noggit/src/main/java/org/apache/noggit/JSONUtil.java Fri Dec 2 18:48:42 2011
@@ -37,9 +37,19 @@ public class JSONUtil {
public static String toJSON(Object o) {
CharArr out = new CharArr();
new JSONWriter(out).write(o);
- return out.toString();
+ return out.toString();
}

+ /**
+ * @param o The object to convert to JSON
+ * @param indentSize The number of space characters to use as an indent (default 2). 0=newlines but no spaces, -1=no indent at all.
+ * @return
+ */
+ public static String toJSON(Object o, int indentSize) {
+ CharArr out = new CharArr();
+ new JSONWriter(out,indentSize).write(o);
+ return out.toString();
+ }

public static void writeNumber(int number, CharArr out) {
out.write(Integer.toString(number));
@@ -92,7 +102,12 @@ public class JSONUtil {
if (ch <= 0x1F) {
unicodeEscape(ch,out);
} else {
- out.write(ch);
+ // These characters are valid JSON, but not valid JavaScript
+ if (ch=='\u2028' || ch=='\u2029') {
+ unicodeEscape(ch,out);
+ } else {
+ out.write(ch);
+ }
}
}
}
@@ -117,7 +132,12 @@ public class JSONUtil {
if (ch <= 0x1F) {
unicodeEscape(ch,out);
} else {
- out.write(ch);
+ // These characters are valid JSON, but not valid JavaScript
+ if (ch=='\u2028' || ch=='\u2029') {
+ unicodeEscape(ch,out);
+ } else {
+ out.write(ch);
+ }
}
}
}

Copied: labs/noggit/src/main/java/org/apache/noggit/JSONWriter.java (from r1099567, labs/noggit/src/main/java/org/apache/noggit/TextWriter.java)
URL: http://svn.apache.org/viewvc/labs/noggit/src/main/java/org/apache/noggit/JSONWriter.java?p2=labs/noggit/src/main/java/org/apache/noggit/JSONWriter.java&p1=labs/noggit/src/main/java/org/apache/noggit/TextWriter.java&r1=1099567&r2=1209632&rev=1209632&view=diff
==============================================================================
--- labs/noggit/src/main/java/org/apache/noggit/TextWriter.java (original)
+++ labs/noggit/src/main/java/org/apache/noggit/JSONWriter.java Fri Dec 2 18:48:42 2011
@@ -23,48 +23,40 @@ import java.util.*;
* @author yonik
* @version $Id$
*/
-public abstract class TextWriter {
- public abstract void writeNull();
-
- public abstract void writeString(CharSequence str);
-
- public abstract void writeString(CharArr str);
-
- public abstract void writeStringStart();
- public abstract void writeStringChars(CharArr partialStr);
- public abstract void writeStringEnd();
-
- public abstract void write(long number);
- public abstract void write(int number);
- public void write(short number) { write ((int)number); }
- public void write(byte number) { write((int)number); }
-
- public abstract void write(double number);
- public abstract void write(float number);
-
- public abstract void write(boolean bool);
-
-
- /** A char[] may be either be a string, or a list of characters.
- * It's up to the implementation to decide.
+public class JSONWriter {
+ int level;
+ int indent;
+ final CharArr out;
+
+ /**
+ * @param out the CharArr to write the output to.
+ * @param indentSize The number of space characters to use as an indent (default 2). 0=newlines but no spaces, -1=no indent at all.
*/
- public abstract void write(char[] val);
-
- public abstract void writeNumber(CharArr digits);
-
- public abstract void writePartialNumber(CharArr digits);
-
- public abstract void startObject();
-
- public abstract void endObject();
-
- public abstract void startArray();
+ public JSONWriter(CharArr out, int indentSize) {
+ this.out = out;
+ this.indent = indentSize;
+ }

- public abstract void endArray();
+ public JSONWriter(CharArr out) {
+ this(out, 2);
+ }

- public abstract void writeValueSeparator();
+ public void setIndentSize(int indentSize) {
+ this.indent = indentSize;
+ }

- public abstract void writeNameSeparator();
+ public void indent() {
+ if (indent >= 0) {
+ out.write('\n');
+ if (indent > 0) {
+ int spaces = level*indent;
+ out.reserve(spaces);
+ for (int i=0; i<spaces; i++) {
+ out.unsafeWrite(' ');
+ }
+ }
+ }
+ }

public void write(Object o) {
if (o == null) {
@@ -106,12 +98,17 @@ public abstract class TextWriter {
} else if (o instanceof byte[]) {
write((byte[])o);
} else {
- writeString(o.toString());
+ handleUnknownClass(o);
}
}

+ public void handleUnknownClass(Object o) {
+ writeString(out.toString());
+ }
+
public void write(Map val) {
startObject();
+ int sz = val.size();
boolean first = true;
for (Map.Entry entry : (Set<Map.Entry>)val.entrySet()) {
if (first) {
@@ -119,6 +116,7 @@ public abstract class TextWriter {
} else {
writeValueSeparator();
}
+ if (sz>1) indent();
writeString(entry.getKey().toString());
writeNameSeparator();
write(entry.getValue());
@@ -128,6 +126,7 @@ public abstract class TextWriter {

public void write(Collection val) {
startArray();
+ int sz = val.size();
boolean first = true;
for (Object o : val) {
if (first) {
@@ -135,6 +134,7 @@ public abstract class TextWriter {
} else {
writeValueSeparator();
}
+ if (sz>1) indent();
write(o);
}
endArray();
@@ -241,5 +241,94 @@ public abstract class TextWriter {
endArray();
}

+
+ public void write(short number) { write ((int)number); }
+ public void write(byte number) { write((int)number); }
+
+
+ public void writeNull() {
+ JSONUtil.writeNull(out);
+ }
+
+ public void writeString(CharSequence str) {
+ JSONUtil.writeString(str,0,str.length(),out);
+ }
+
+ public void writeString(CharArr str) {
+ JSONUtil.writeString(str,out);
+ }
+
+ public void writeStringStart() {
+ out.write('"');
+ }
+
+ public void writeStringChars(CharArr partialStr) {
+ JSONUtil.writeStringPart(partialStr.getArray(), partialStr.getStart(), partialStr.getEnd(), out);
+ }
+
+ public void writeStringEnd() {
+ out.write('"');
+ }
+
+ public void write(long number) {
+ JSONUtil.writeNumber(number,out);
+ }
+
+ public void write(int number) {
+ JSONUtil.writeNumber(number,out);
+ }
+
+ public void write(double number) {
+ JSONUtil.writeNumber(number,out);
+ }
+
+ public void write(float number) {
+ JSONUtil.writeNumber(number,out);
+ }
+
+ public void write(boolean bool) {
+ JSONUtil.writeBoolean(bool,out);
+ }
+
+ public void write(char[] val) {
+ JSONUtil.writeString(val, 0, val.length, out);
+ }
+
+ public void writeNumber(CharArr digits) {
+ out.write(digits);
+ }
+
+ public void writePartialNumber(CharArr digits) {
+ out.write(digits);
+ }
+
+ public void startObject() {
+ out.write('{');
+ level++;
+ }
+
+ public void endObject() {
+ out.write('}');
+ level--;
+ }
+
+ public void startArray() {
+ out.write('[');
+ level++;
+ }
+
+ public void endArray() {
+ out.write(']');
+ level--;
+ }
+
+ public void writeValueSeparator() {
+ out.write(',');
+ }
+
+ public void writeNameSeparator() {
+ out.write(':');
+ }
+
}

Added: labs/noggit/src/test/java/org/apache/noggit/TestJSONWriter.java
URL: http://svn.apache.org/viewvc/labs/noggit/src/test/java/org/apache/noggit/TestJSONWriter.java?rev=1209632&view=auto
==============================================================================
--- labs/noggit/src/test/java/org/apache/noggit/TestJSONWriter.java (added)
+++ labs/noggit/src/test/java/org/apache/noggit/TestJSONWriter.java Fri Dec 2 18:48:42 2011
@@ -0,0 +1,66 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.noggit;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author yonik
+ * @version $Id$
+ */
+public class TestJSONWriter extends TestCase {
+
+ // note - TestObjectBuilder also exercises JSONWriter
+
+ public void test(String expected, Object val, int indent) throws IOException {
+ expected = expected.replace('\'','"');
+ String s1 = JSONUtil.toJSON(val, indent);
+ assertEquals(s1, expected);
+ }
+
+ public static List L(Object... lst) {
+ return Arrays.asList(lst);
+ }
+ public static Object[] A(Object... lst) {
+ return lst;
+ }
+ public static Map O(Object... lst) {
+ LinkedHashMap map = new LinkedHashMap();
+ for (int i=0; i<lst.length; i+=2) {
+ map.put(lst[i].toString(), lst[i+1]);
+ }
+ return map;
+ }
+
+ // NOTE: the specifics of indentation may change in the future!
+ public void testWriter() throws Exception {
+ test("[]",L(),2);
+ test("{}",O(),2);
+ test("[\n 10,\n 20]", L(10,20), 2);
+ test("{\n 'a':10,\n 'b':{\n 'c':20,\n 'd':30}}", O("a",10,"b",O("c",20,"d",30)), 1);
+
+ test("['\\r\\n\\u0000\\'']", L("\r\n\u0000\""),2);
+
+ }
+}

Propchange: labs/noggit/src/test/java/org/apache/noggit/TestJSONWriter.java
------------------------------------------------------------------------------
svn:eol-style = native

Propchange: labs/noggit/src/test/java/org/apache/noggit/TestJSONWriter.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL

Modified: labs/noggit/src/test/java/org/apache/noggit/TestObjectBuilder.java
URL: http://svn.apache.org/viewvc/labs/noggit/src/test/java/org/apache/noggit/TestObjectBuilder.java?rev=1209632&r1=1209631&r2=1209632&view=diff
==============================================================================
--- labs/noggit/src/test/java/org/apache/noggit/TestObjectBuilder.java (original)
+++ labs/noggit/src/test/java/org/apache/noggit/TestObjectBuilder.java Fri Dec 2 18:48:42 2011
@@ -32,14 +32,14 @@ public class TestObjectBuilder extends T
val = val.replace('\'','"');
Object v = ObjectBuilder.fromJSON(val);

- String s1 = JSONUtil.toJSON(v);
- String s2 = JSONUtil.toJSON(expected);
+ String s1 = JSONUtil.toJSON(v,-1);
+ String s2 = JSONUtil.toJSON(expected,-1);
assertEquals(s1, s2);

// not make sure that it round-trips correctly
JSONParser p2 = TestJSONParser.getParser(s1);
Object v2 = ObjectBuilder.getVal(p2);
- String s3 = JSONUtil.toJSON(v2);
+ String s3 = JSONUtil.toJSON(v2,-1);
assertEquals(s1, s3);
}

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@labs.apache.org
For additional commands, e-mail: commits-help@labs.apache.org

No comments:

Post a Comment