Broadcast on Broadcast off
The Documentation for Project Zero has moved. Please update your bookmarks to: http://www.projectzero.org/documentation/
Table of
Contents...
Hide

Project Zero Developer’s Guide

Concepts and components
Basic concepts overview
Event processing
Writing Java handlers
Writing Groovy handlers
Firing events
Global Context
Global Context reference
Application directory layout
Virtualized directories
Assemble
PHP
Features and configuration
Configuration
Debugging
Dependencies
Packaging
Application classpath
Logging and tracing
RESTful resources
RESTful documentation
File serving
Response rendering
Validators and validation
HTTP error handling
Calling a remote resource
Using the Connection API
Sending an email using EmailConnection
Configuring destinations
Configuring protocols
Configuring connection handlers
Creating a connection handler
Creating a custom protocol transport
Simple logging connection handlers
Protocol reference
Client programming with Dojo
Runtime options
Deployment modifications
HTTP configuration
SSL configuration
Proxy configuration
Extending the CLI
Security considerations
Authentication
OpenID authentication
Extending security
Security tokens
CSRF prevention support
Extending token support
Leveraging TAI
User service
File based user service
LDAP user service
Extending user service
Security Utilities
Leveraging XOREncoder
Extensions
Atom support
RSS support
JSON support
XMLEncoder
REST to SOAP extension
URIUtils
Developer Web tools
Database setup tools
Configuring data access
Common query patterns
Advanced query patterns
Update patterns
Local database transactions
Extending data access
Configuration vendor differences
PHP data access
Resource model
Configuring ZRM
Resource model declaration
Programmatic model API
HTTP REST API
A ZRM mini tutorial
Active content filtering support
Default filters
Custom filters
Runtime management
Management commands
Zero socket opener
Other extension modules
Amazon E-commerce service
Flickr service
WeatherZero forecast service
Wikipedia service
Reference
Zero command line interface
JavaDoc - Public API
JavaDoc - Public SPI
JavaDoc - All Classes

 

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.Json is the primary Zero API for working with JSON, including parsing, serializing, and converting representations.

Common APIs:

public class Json {
        
        /** Parse or decode a JSON encoded data from a String, InputStream or Reader into an appropriate Java object*/
        public static Object decode(String str) throws IOException { ... }
        public static Object decode(InputStream is) throws IOException { ... }
        public static Object decode(Reader reader) throws IOException { ... }
        public static Object decodeFromUrl(String urlString) throws IOException { ... }
        
        /** Variation of the decode functions useful when decoding JSON objects into Maps and the order of the elements are to be preserved */
        public static Object decode(String str, boolean ordered) throws IOException { ... }
        public static Object decode(InputStream is, boolean ordered) throws IOException { ... }
        public static Object decode(Reader reader, boolean ordered) throws IOException { ... }
        public static Object decodeFromUrl(String urlString, boolean ordered) throws IOException { ... }      
        
        /** Serialize or encode a Java object as JSON data */
        public static String encode(Object obj) throws IllegalArgumentException, IntrospectionException, IllegalAccessException, InvocationTargetException, IOException{ ... } 
        public static void encode(Object obj, OutputStream os) throws IllegalArgumentException, IntrospectionException, IllegalAccessException, InvocationTargetException, IOException{ ... }
        public static void encode(Object obj, Writer writer) throws IllegalArgumentException, IntrospectionException, IllegalAccessException, InvocationTargetException, IOException{ ... }
        
        /** Encode a Java object with formatting */
        public static String encode(Object obj, boolean formatted) throws IllegalArgumentException, IntrospectionException, IllegalAccessException, InvocationTargetException, IOException{ ... }
        public static void encode(Object obj, OutputStream os, boolean formatted) throws IllegalArgumentException, IntrospectionException, IllegalAccessException, InvocationTargetException, IOException { ... }
        public static void encode(Object obj, Writer writer, boolean formatted) throws IllegalArgumentException, IntrospectionException, IllegalAccessException, InvocationTargetException, IOException { ... }
        
        /** Convert a decoded object into a custom Java object */
        public static <T> T toObject(Object jsonObj, Class<T> type) { ... }
        
}

decode() returns one of the following Java types:

  • java.lang.String
  • java.lang.Number
  • java.lang.Boolean
  • java.util.Map, which represents JSON objects
  • java.util.List, which represents JSON arrays
  • null

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;

String result = Json.encode(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:

zput("/request/view", "JSON");
zput("/request/json/output", obj);
zero.core.views.ViewEngine.render();

Groovy example:

request.view="JSON"
request.json.output=obj
render()

PHP example:

zput("/request/view", "JSON");
zput("/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 extends Encoder {
        /**
        * Convert JSON representation to a Java object.
        */
        public Object toObject(Object json);
        
}

public interface Encoder {
        /**
        * The implementer of this interface serializes a custom java object as json using the serializer provided. 
        * The custom encoder is declared using the global context. This interface provides a object reference map 
        * as a parameter which can be used find and add references to Java objects that might already be serialized. 
        * It is a good practice to add a reference to the object being serialized prior to serializing it so that any circular
        * references to the object can be resolved. Any complex (array or object) attribute added to the serialized stream
        * should be updated in reference map with the object reference as a key and its JSON reference as its value.
        *
        * In general the JSON reference to complex attributes are computed as follows. Any array reference to a complex
        * attribute concatenates the index of the attribute enclosed by "[" and "]" to the JSON reference of the containing
        * object. For instance jref + "[" + index + "]". Any object reference to a complex attribute appends
        * the name of the attribute separated by a period to the containing jref. For instance 
        *  jref + "." + attributeName .
        * 
        * @param object The object that needs to be serialized.
        * @param refMap a reference Map of objects that have been serialized to their JSON references. 
        * This map should updated with the reference of the object being serialized and any of its elements.
        * @param jref the JSON reference for the containing object. 
        * @param serializer the serializer object that needs to be used to create the custom json encoding for the object.
        */
        public void write(Object obj, Map<Object, String> refMap, String jref,  Serializer serializer) throws IllegalArgumentException, IntrospectionException, IllegalAccessException, InvocationTargetException, IOException ;
        
}

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.Writable" : "zero.json.converters.groovy.lang.WritableConverter"
}

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 and interfaces. converters are checked first.

r21 - 07 Feb 2008 - 13:10:43 - madhu
Syndicate this site RSS ATOM
Copyright 2007 © IBM Corporation | Privacy | Terms of Use | About this site