You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by jw...@apache.org on 2015/12/12 00:30:17 UTC
[2/7] groovy git commit: Support for Array and Iterable not just
Collection in StreamingJsonBuilder (closes #203)
Support for Array and Iterable not just Collection in StreamingJsonBuilder (closes #203)
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/61651590
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/61651590
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/61651590
Branch: refs/heads/GROOVY_2_4_X
Commit: 616515909b80c3a01474251af96b8bac5fb44e82
Parents: 5e034d3
Author: graemerocher <gr...@gmail.com>
Authored: Wed Dec 2 11:13:25 2015 +0100
Committer: John Wagenleitner <jw...@apache.org>
Committed: Fri Dec 11 14:39:57 2015 -0800
----------------------------------------------------------------------
.../src/main/java/groovy/json/JsonOutput.java | 18 +-
.../java/groovy/json/StreamingJsonBuilder.java | 171 +++++++++++++------
.../groovy/json/StreamingJsonBuilderTest.groovy | 45 +++++
3 files changed, 175 insertions(+), 59 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/61651590/subprojects/groovy-json/src/main/java/groovy/json/JsonOutput.java
----------------------------------------------------------------------
diff --git a/subprojects/groovy-json/src/main/java/groovy/json/JsonOutput.java b/subprojects/groovy-json/src/main/java/groovy/json/JsonOutput.java
index b9a4e4b..8bee49d 100644
--- a/subprojects/groovy-json/src/main/java/groovy/json/JsonOutput.java
+++ b/subprojects/groovy-json/src/main/java/groovy/json/JsonOutput.java
@@ -305,10 +305,7 @@ public class JsonOutput {
} else if (Enum.class.isAssignableFrom(objectClass)) {
buffer.addQuoted(((Enum<?>) object).name());
}else if (File.class.isAssignableFrom(objectClass)){
- Map<?, ?> properties = DefaultGroovyMethods.getProperties(object);
- properties.remove("class");
- properties.remove("declaringClass");
- properties.remove("metaClass");
+ Map<?, ?> properties = getObjectProperties(object);
//Clean up all recursive references to File objects
Iterator<? extends Map.Entry<?, ?>> iterator = properties.entrySet().iterator();
while(iterator.hasNext()){
@@ -320,15 +317,20 @@ public class JsonOutput {
writeMap(properties, buffer);
} else {
- Map<?, ?> properties = DefaultGroovyMethods.getProperties(object);
- properties.remove("class");
- properties.remove("declaringClass");
- properties.remove("metaClass");
+ Map<?, ?> properties = getObjectProperties(object);
writeMap(properties, buffer);
}
}
}
+ private static Map<?, ?> getObjectProperties(Object object) {
+ Map<?, ?> properties = DefaultGroovyMethods.getProperties(object);
+ properties.remove("class");
+ properties.remove("declaringClass");
+ properties.remove("metaClass");
+ return properties;
+ }
+
/**
* Serializes any char sequence and writes it into specified buffer.
http://git-wip-us.apache.org/repos/asf/groovy/blob/61651590/subprojects/groovy-json/src/main/java/groovy/json/StreamingJsonBuilder.java
----------------------------------------------------------------------
diff --git a/subprojects/groovy-json/src/main/java/groovy/json/StreamingJsonBuilder.java b/subprojects/groovy-json/src/main/java/groovy/json/StreamingJsonBuilder.java
index f96d8f6..f37789c 100644
--- a/subprojects/groovy-json/src/main/java/groovy/json/StreamingJsonBuilder.java
+++ b/subprojects/groovy-json/src/main/java/groovy/json/StreamingJsonBuilder.java
@@ -205,10 +205,8 @@ public class StreamingJsonBuilder extends GroovyObjectSupport {
* @param coll a collection
* @param c a closure used to convert the objects of coll
*/
- public Object call(Collection coll, @DelegatesTo(StreamingJsonDelegate.class) Closure c) throws IOException {
- StreamingJsonDelegate.writeCollectionWithClosure(writer, coll, c);
-
- return null;
+ public Object call(Iterable coll, @DelegatesTo(StreamingJsonDelegate.class) Closure c) throws IOException {
+ return StreamingJsonDelegate.writeCollectionWithClosure(writer, coll, c);
}
/**
@@ -287,7 +285,7 @@ public class StreamingJsonBuilder extends GroovyObjectSupport {
* @param coll a collection
* @param c a closure used to convert the objects of coll
*/
- public void call(String name, Collection coll, @DelegatesTo(StreamingJsonDelegate.class) Closure c) throws IOException {
+ public void call(String name, Iterable coll, @DelegatesTo(StreamingJsonDelegate.class) Closure c) throws IOException {
writer.write(JsonOutput.OPEN_BRACE);
writer.write(JsonOutput.toJson(name));
writer.write(JsonOutput.COLON);
@@ -405,28 +403,46 @@ public class StreamingJsonBuilder extends GroovyObjectSupport {
if (args != null && Object[].class.isAssignableFrom(args.getClass())) {
Object[] arr = (Object[]) args;
try {
- if (arr.length == 0) {
- call(name);
- } else if (arr.length == 1) {
- if (arr[0] instanceof Closure) {
- final Closure callable = (Closure) arr[0];
- call(name, callable);
- } else if (arr[0] instanceof Map) {
- final Map<String, Map> map = Collections.singletonMap(name, (Map) arr[0]);
- call(map);
- } else {
+ switch(arr.length) {
+ case 0:
+ call(name);
+ break;
+ case 1:
+ if (arr[0] instanceof Closure) {
+ final Closure callable = (Closure) arr[0];
+ call(name, callable);
+ } else if (arr[0] instanceof Map) {
+ final Map<String, Map> map = Collections.singletonMap(name, (Map) arr[0]);
+ call(map);
+ } else {
+ notExpectedArgs = true;
+ }
+ break;
+ case 2:
+ final Object first = arr[0];
+ final Object second = arr[1];
+ final boolean isClosure = second instanceof Closure;
+
+ if(isClosure && first instanceof Map ) {
+ final Closure callable = (Closure) second;
+ call(name, (Map)first, callable);
+ }
+ else if(isClosure && first instanceof Iterable) {
+ final Iterable coll = (Iterable) first;
+ final Closure callable = (Closure) second;
+ call(name, coll, callable);
+ }
+ else if(isClosure && first.getClass().isArray()) {
+ final Iterable coll = Arrays.asList((Object[])first);
+ final Closure callable = (Closure) second;
+ call(name, coll, callable);
+ }
+ else {
+ notExpectedArgs = true;
+ }
+ break;
+ default:
notExpectedArgs = true;
- }
- } else if (arr.length == 2 && arr[0] instanceof Map && arr[1] instanceof Closure) {
- Map map = (Map) arr[0];
- final Closure callable = (Closure) arr[1];
- call(name, map, callable);
- } else if (StreamingJsonDelegate.isCollectionWithClosure(arr)) {
- final Collection coll = (Collection) arr[0];
- final Closure callable = (Closure) arr[1];
- call(name, coll, callable);
- } else {
- notExpectedArgs = true;
}
} catch (IOException ioe) {
throw new JsonException(ioe);
@@ -447,9 +463,9 @@ public class StreamingJsonBuilder extends GroovyObjectSupport {
*/
public static class StreamingJsonDelegate extends GroovyObjectSupport {
- private Writer writer;
- private boolean first;
- private State state;
+ protected final Writer writer;
+ protected boolean first;
+ protected State state;
public StreamingJsonDelegate(Writer w, boolean first) {
@@ -457,21 +473,42 @@ public class StreamingJsonBuilder extends GroovyObjectSupport {
this.first = first;
}
+ public Writer getWriter() {
+ return writer;
+ }
+
public Object invokeMethod(String name, Object args) {
if (args != null && Object[].class.isAssignableFrom(args.getClass())) {
try {
Object[] arr = (Object[]) args;
- if (arr.length == 1) {
- final Object value = arr[0];
- call(name, value);
- } else if (isCollectionWithClosure(arr)) {
- final Collection coll = (Collection) arr[0];
- final Closure callable = (Closure) arr[1];
- call(name, coll, callable);
- } else {
- final List<Object> list = Arrays.asList(arr);
- call(name, list);
+ final int len = arr.length;
+ switch (len) {
+ case 1:
+ final Object value = arr[0];
+ call(name, value);
+ return null;
+ case 2:
+ if(arr[len -1] instanceof Closure) {
+ final Object obj = arr[0];
+ final Closure callable = (Closure) arr[1];
+ if(obj instanceof Iterable) {
+ call(name, (Iterable)obj, callable);
+ return null;
+ }
+ else if(obj.getClass().isArray()) {
+ call(name, Arrays.asList( (Object[])obj), callable);
+ return null;
+ }
+ else {
+ call(name, obj, callable);
+ return null;
+ }
+ }
+ default:
+ final List<Object> list = Arrays.asList(arr);
+ call(name, list);
+
}
} catch (IOException ioe) {
throw new JsonException(ioe);
@@ -528,7 +565,7 @@ public class StreamingJsonBuilder extends GroovyObjectSupport {
* @param coll a collection
* @param c a closure used to convert the objects of coll
*/
- public void call(String name, Collection coll, Closure c) throws IOException {
+ public void call(String name, Iterable coll, Closure c) throws IOException {
writeName(name);
writeObjects(coll, c);
}
@@ -546,6 +583,33 @@ public class StreamingJsonBuilder extends GroovyObjectSupport {
}
/**
+ * Writes the name and value of a JSON attribute
+ *
+ * @param name The attribute name
+ * @param value The value
+ * @throws IOException
+ */
+ public void call(String name, Object value, @DelegatesTo(StreamingJsonDelegate.class) Closure callable) throws IOException {
+ writeName(name);
+ verifyValue();
+ writeObject(writer, value, callable);
+ }
+ /**
+ * Writes the name and another JSON boject
+ *
+ * @param name The attribute name
+ * @param value The value
+ * @throws IOException
+ */
+ public void call(String name,@DelegatesTo(StreamingJsonDelegate.class) Closure value) throws IOException {
+ writeName(name);
+ verifyValue();
+ writer.write(JsonOutput.OPEN_BRACE);
+ StreamingJsonDelegate.cloneDelegateAndGetContent(writer, value);
+ writer.write(JsonOutput.CLOSE_BRACE);
+
+ }
+ /**
* Writes an unescaped value. Note: can cause invalid JSON if passed JSON is invalid
*
* @param name The attribute name
@@ -558,12 +622,12 @@ public class StreamingJsonBuilder extends GroovyObjectSupport {
}
- private void writeObjects(Collection coll, @DelegatesTo(StreamingJsonDelegate.class) Closure c) throws IOException {
+ private void writeObjects(Iterable coll, @DelegatesTo(StreamingJsonDelegate.class) Closure c) throws IOException {
verifyValue();
writeCollectionWithClosure(writer, coll, c);
}
- private void verifyValue() {
+ protected void verifyValue() {
if(state == State.VALUE) {
throw new IllegalStateException("Cannot write value when value has just been written. Write a name first!");
}
@@ -573,7 +637,7 @@ public class StreamingJsonBuilder extends GroovyObjectSupport {
}
- private void writeName(String name) throws IOException {
+ protected void writeName(String name) throws IOException {
if(state == State.NAME) {
throw new IllegalStateException("Cannot write a name when a name has just been written. Write a value first!");
}
@@ -589,21 +653,21 @@ public class StreamingJsonBuilder extends GroovyObjectSupport {
writer.write(JsonOutput.COLON);
}
- private void writeValue(Object value) throws IOException {
+ protected void writeValue(Object value) throws IOException {
verifyValue();
writer.write(JsonOutput.toJson(value));
}
- private void writeArray(List<Object> list) throws IOException {
+ protected void writeArray(List<Object> list) throws IOException {
verifyValue();
writer.write(JsonOutput.toJson(list));
}
public static boolean isCollectionWithClosure(Object[] args) {
- return args.length == 2 && args[0] instanceof Collection && args[1] instanceof Closure;
+ return args.length == 2 && args[0] instanceof Iterable && args[1] instanceof Closure;
}
- public static Object writeCollectionWithClosure(Writer writer, Collection coll, Closure closure) throws IOException {
+ public static Object writeCollectionWithClosure(Writer writer, Iterable coll, Closure closure) throws IOException {
writer.write(JsonOutput.OPEN_BRACKET);
boolean first = true;
for (Object it : coll) {
@@ -613,16 +677,21 @@ public class StreamingJsonBuilder extends GroovyObjectSupport {
first = false;
}
- writer.write(JsonOutput.OPEN_BRACE);
- curryDelegateAndGetContent(writer, closure, it);
- writer.write(JsonOutput.CLOSE_BRACE);
+ writeObject(writer, it, closure);
}
writer.write(JsonOutput.CLOSE_BRACKET);
return writer;
}
- public static void cloneDelegateAndGetContent(Writer w, Closure c) {
+ private static void writeObject(Writer writer, Object object, Closure closure) throws IOException {
+ writer.write(JsonOutput.OPEN_BRACE);
+ curryDelegateAndGetContent(writer, closure, object);
+ writer.write(JsonOutput.CLOSE_BRACE);
+ }
+
+ public static void cloneDelegateAndGetContent(Writer w, Closure c)
+ {
cloneDelegateAndGetContent(w, c, true);
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/61651590/subprojects/groovy-json/src/test/groovy/groovy/json/StreamingJsonBuilderTest.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-json/src/test/groovy/groovy/json/StreamingJsonBuilderTest.groovy b/subprojects/groovy-json/src/test/groovy/groovy/json/StreamingJsonBuilderTest.groovy
index 19f4477..9bae655 100644
--- a/subprojects/groovy-json/src/test/groovy/groovy/json/StreamingJsonBuilderTest.groovy
+++ b/subprojects/groovy-json/src/test/groovy/groovy/json/StreamingJsonBuilderTest.groovy
@@ -231,6 +231,51 @@ class StreamingJsonBuilderTest extends GroovyTestCase {
}
}
+ void testIterableAndClosure() {
+ def authors = [new Author(name: "Guillaume"), new Author(name: "Jochen"), new Author(name: "Paul")]
+ Iterable it = [iterator:{->
+ authors.iterator()
+ }] as Iterable
+ new StringWriter().with { w ->
+ def json = new StreamingJsonBuilder(w)
+ json it, { Author author ->
+ name author.name
+ }
+
+ assert w.toString() == '[{"name":"Guillaume"},{"name":"Jochen"},{"name":"Paul"}]'
+ }
+ }
+
+ void testMethodWithIterableAndClosure() {
+ def authors = [new Author(name: "Guillaume"), new Author(name: "Jochen"), new Author(name: "Paul")]
+ Iterable it = [iterator:{->
+ authors.iterator()
+ }] as Iterable
+
+ new StringWriter().with { w ->
+ def json = new StreamingJsonBuilder(w)
+ json.authors it, { Author author ->
+ name author.name
+ }
+
+ assert w.toString() == '{"authors":[{"name":"Guillaume"},{"name":"Jochen"},{"name":"Paul"}]}'
+ }
+ }
+
+ void testMethodWithArrayAndClosure() {
+ def authors = [new Author(name: "Guillaume"), new Author(name: "Jochen"), new Author(name: "Paul")]
+
+
+ new StringWriter().with { w ->
+ def json = new StreamingJsonBuilder(w)
+ json.authors authors as Author[], { Author author ->
+ name author.name
+ }
+
+ assert w.toString() == '{"authors":[{"name":"Guillaume"},{"name":"Jochen"},{"name":"Paul"}]}'
+ }
+ }
+
void testMethodWithCollectionAndClosure() {
def authors = [new Author(name: "Guillaume"), new Author(name: "Jochen"), new Author(name: "Paul")]