| | |
|
|
|
JSON support
The zero.core package includes support for JavaScript Object Notation (JSON) data structures. The following sections of this article provide information about JSON support:
JSON APIs
zero.json.JsonType is the primary Zero API for working with JSON, including parsing, serializing, and converting representations.
Common APIs:
public class JsonType {
/**
* Instantiate from a base JSON representation:
* JSONObject, JSONArray, String, Number, Boolean, null
*/
public JsonType(Object json) { ... }
/** Parse */
public static JsonType fromData(String str) throws IOException { ... }
public static JsonType fromData(InputStream is) throws IOException { ... }
public static JsonType fromData(Reader reader) throws IOException { ... }
public static JsonType fromUrl(String str) throws IOException { ... }
/** Serialize */
public void toData(OutputStream os) throws IOException { ... }
public void toData(OutputStream os, boolean formatted) throws IOException { ... }
public void toData(Writer writer) throws IOException { ... }
public void toData(Writer writer, boolean formatted) throws IOException { ... }
/** Convert between JSON and custom Java objects */
public static JsonType fromObject(Object o) { ... }
public <T> T toObject(Class<T> c) { ... }
/**
* Returns the base JSON representation.
*/
public Object getJson() { ... }
}
getJson() returns one of the following Java types:
-
java.lang.String
-
java.lang.Number
-
java.lang.Boolean
-
zero.json.java.JSONObject, which extends java.util.HashMaps and represents JSON objects
-
zero.json.java.JSONArray, which extends java.util.ArrayList and represents JSON arrays
-
null
Note that JSONObject and JSONArray only accept types from the above list; attempting to put/add a non-valid type results in an IllegalArgumentException.
By default, conversions between Java objects and JSON operate upon only public properties of the Java objects. "Public properties" of a Java object are properties associated with either public getter/setter methods or public (non-final) fields. Default conversions attempt to use getter/setter methods first.
Custom converters may be incorporated, as noted below.
Circular references
Avoid serializing Java objects that contain circular references: JSON is used to represent data, not objects.
However, if circular references are detected, then the JsonTypes API replaces the references with JavaScript-like pointers with a $jref prefix. For example:
public class A {
public B b;
}
public class B {
public Foo[] foos;
}
public class Foo {
public Bar bar;
}
public class Bar {
public Foo y;
}
...
A a = new A();
a.b = new B();
a.b.foos = new Foo[1];
Foo foo = new Foo();
Bar x = new Bar();
foo.bar = x;
x.y = foo;
a.b.foos[0] = foo;
JSONObject result = JavaToJson.serialize(a);
// result = {"b" : {"foos" : [{"bar" : {"y" : "$jref:this.b.foos[0]"}}]}
The process of converting JSON to Java restores circular references using the same convention. Thus, round-trip conversion is loss-less.
JSON Renderer
Zero provides a library of "renderers" for common output patterns. The common case of serializing a Java object to the response as a JSON representation is codified as a renderer.
Java example:
GlobalContext.put("/request/view", "JSON");
GlobalContext.put("/request/json/output", obj);
zero.core.views.ViewEngine.render();
Groovy example:
request.view="JSON"
request.json.output=obj
render()
PHP example:
put("/request/view", "JSON");
put("/request/json/output", $var);
render_view();
Pretty print
By default, Zero serializes JSON in a compact format. This is efficient for transmission, but not tailored for human consumption. You can force a "pretty print" serialization by adding the following to your application's zero.config file:
[/config/json]
prettyPrint=true
For example, without pretty print:
{"name":"Bob"}
with pretty print:
{
"name": "Bob"
}
Custom converters
Custom converters are Java implementations of zero.json.converters.Converter:
public interface Converter {
/**
* Convert JSON representation to a Java object.
*/
public Object toObject(Object json);
/**
* Convert Java object to a JSON representation.
*/
public Object toJson(Object obj);
}
For consistency, these methods should be complimentary. That is, x.equals(toObject(toJson(x))).
Custom converters are registered via the GlobalContext as class name/converter pairs, such as:
[/config/json/converters]
java.sql.Time=zero.json.converters.java.sql.TimeConverter
java.sql.Timestamp=zero.json.converters.java.sql.TimestampConverter
java.sql.Date=zero.json.converters.java.sql.DateConverter
java.util.Date=zero.json.converters.java.util.DateConverter
[/config/json/derivedConverters]
groovy.lang.GString=zero.json.converters.groovy.lang.GStringConverter
converters and derivedConverters differ in how they are matched. Converters registered under /config/json/converters are invoked when serializing from/parsing to an instance of the specified class; those under /config/json/derivedConverters are checked on superclasses. converters are checked first.
Comparing JSON representations
zero.json.JsonComparator compares two JSON entities (Boolean, Number, String, null, JSONObject, JSONArray) based upon structure and values. It reports the first difference with a JavaScript path pointer (for example docroot.key1.key2[1]).
Notes:
-
public static String zero.json.JsonComparator.compare(Object x, Object y) returns null for a match; otherwise returns a description of the first difference.
|
|
r17 - 29 Oct 2007 - 09:20:05 - steveims
|
|
|
| | |