JSON Binding
Processes deployed to Process Server are available as JSON (JavaScript Object Notation) bindings. Similar to services with XML binding, the services must be WS-I compliant:
- •WSDL portType operation is document-literal.
- •Operation input message has only one part and that part is of element type.
- •Operation output message has only one part and that part is of element type.
JSON Representation of XML Content
In order to invoke a service using JSON, the service request message, which is normally defined in XML, must be represented in JSON. The Process Server represents XML elements in JSON notation based on the methodology described by Google GData convention at http://code.google.com/apis/gdata/json.html.
XML element Represented as a JSON Object
<contactInfo />
JSON Equivalent
{
"contactInfo" : {}
}
Attributes
Element attributes are represented as string properties.
<contactInfo type="home" default="true" />
JSON Equivalent
{
"contactInfo" : {
"type" : "home",
"default": "true"
}
}
In JavaScript, accessing attributes can be done as follows (assuming the JSON data is assigned to variable named doc):
var doc = { "contactInfo" : {
"type": "home",
"default": "true"
}
};
// type attribute is accessed via doc.contactInfo["type"]
// or doc.contactInfo.type.
alert("contact information type: " + doc.contactInfo.type);
Child Elements
Child elements are converted to Object type properties.
<contactInfo type="home" default="true" >
<phone />
</contactInfo>
JSON equivalent (see 'phone' element object in line 5):
{
"contactInfo" : {
"type" : "home",
"default": "true",
"phone" : {}
}
}
Element text
Text values of elements are converted to string property named $t. The following shows how the <phone/> element text value "(203-555-1212)" is represented.
<contactInfo type="home" default="true" >
<phone type="voice">203-555-1212</phone>
</contactInfo>
JSON:
{
"contactInfo" : {
"type" : "home",
"default": "true",
"phone" : {
"type" : "voice",
"$t" : "203-555-1212"
}
}
}
Example JavaScript:
// JavaScript:
var doc = { .... }; // define json
// the phone number is doc.contactInfo.phone.$t
alert("phone number: " + doc.contactInfo.phone.$t);
Repeating elements
Elements that may appear more than once are converted to an array of objects:
<contactInfo type="home" default="true" >
<phone type="voice">203-555-1212</phone>
<phone type="fax">203-555-1213</phone>
</contactInfo>
JSON:
{
"contactInfo" : {
"type" : "home",
"default": "true",
"phone" : [
{
"type" : "voice",
"$t" : "203-555-1212"
},
{
"type" : "fax",
"$t" : "203-555-1213"
}
]
}
}
Example:
// JavaScript:
// Access phone via array index: doc.contactInfo.phone[0].$t
var i;
for (i=0; i < doc.contactInfo.phone.length; i++) {
alert( "phone " + i + " = " + doc.contactInfo.phone[i].$t);
}
Namespace Prefix
If an element has a namespace prefix, the prefix and element name are concatenated using "$". Attribute prefixes are presented in the same way. For example, <c:contactInfo> is represented as { c$contactInfo: {} }. Attribute xmlns:c="urn:ns:contactinfo" is represented as xmlns$c:"urn:ns:contactinfo". The following example XML uses prefixed elements xmlns:p="urn:ns:person", xmlns:c="urn:ns:contactinfo", and also two elements that are unqualified (email and photo).
<p:person xmlns:p="urn:ns:person">
<p:firstName>John</p:firstName>
<p:lastName>Smith</p:lastName>
<c:contactInfo xmlns:c="urn:ns:contactinfo" type="home" default="true" >
<c:phone type="voice">203-555-1212</c:phone>
<c:phone type="fax">203-555-1213</c:phone>
<email>jsmith@example.com</email>Happy
</c:contactInfo>
<photo>http://example.com/jsmith/profile.png</photo>
</p:person>
JSON
{
"p$person" : {
"xmlns$p" : "urn:ns:person",
"p$firstName" : {
"$t" : "John"
},
"p$lastName" : {
"$t" : "Smith"
},
"c$contactInfo" : {
"xmlns$c" : "urn:ns:contactinfo",
"default" : "true",
"type" : "home",
"c$phone" : [
{
"type" : "voice",
"$t" : "203-555-1212"
},
{
"type" : "fax",
"$t" : "203-555-1213"
}
],
"email" : {
"$t" : "jsmith@example.com"
}
},
"photo" : {
"$t" : "http://example.com/jsmith/profile.png"
}
}
}
Example:
// JavaScript:
var doc = { ... }; // JSON representation of person.
// first Name: /p:person/p:firstName/text()
alert("firstName =" + doc.p$person.p$firstName.$t);
// photo /p:person/photo/text()
alert("photo =" + doc.p$person.photo.$t);
// email /p:person/c:contactInfo/email/text()
alert("email =" + doc.p$person.c$contactInfo.email.$t);
var i;
for (i=0; i < doc.p$person.c$contactInfo.c$phone.length; i++) {
alert( "phone " + i + "=" + doc.p$person.c$contactInfo.c$phone[i].$t);
}
Default namespace
Instead of using elements with prefixes, you can declare the namespace on each element. For example instead of <c:contactInfo xmlns:c="urn:ns:contactinfo">, you can use <contactInfo xmlns="urn:ns:contactinfo">. Now, the JSON object properties do not have "$" in the middle of their property names, which is easier to use; for example, contactInfo instead of c$contactInfo. Process Server always uses namespaces when it serializes (converts) XML to JSON.
The prefixed element <p:person xmlns:p="urn:ns:person"> used prviously can be represented using the default namespace of each element (when the namespace changes):
<person xmlns="urn:ns:person">
<firstName>John</firstName>
<lastName>Smith</lastName>
<contactInfo xmlns="urn:ns:contactinfo" type="home" default="true" >
<phone type="voice">203-555-1212</phone>
<phone type="fax">203-555-1213</phone>
<email xmlns="">jsmith@example.com</email>
</contactInfo>
<photo xmlns="">http://example.com/jsmith/profile.png</photo>
</person>
The following shows the JSON representation and how it is used in JavaScript. Notice that it is easier to read and use compared to JSON properties notation that concatenates a prefix/element with a $. Both formats work; however Process Server always uses the non-prefix method when it converts XML to JSON.
{
"person" : {
"xmlns" : "urn:ns:person",
"firstName" : {
"$t" : "John"
},
"lastName" : {
"$t" : "Smith"
},
"contactInfo" : {
"xmlns" : "urn:ns:contactinfo",
"default" : "true",
"type" : "home",
"phone" : [
{
"type" : "voice",
"$t" : "203-555-1212"
},
{
"type" : "fax",
"$t" : "203-555-1213"
}
],
"email" : {
"xmlns" : "",
"$t" : "jsmith@example.com"
}
},
"photo" : {
"xmlns" : "",
"$t" : "http://example.com/jsmith/profile.png"
}
}
}
Example:
// JavaScript:
var doc = { ... }; // JSON representation of person using default namespace (and no prefixes).
// first Name:
alert("firstName =" + doc.person.firstName.$t);
// (compare above to prefixed version doc.p$person.p$firstName.$t)
// photo
alert("photo =" + doc.person.photo.$t);
// (compare to prefixed version doc.p$person.photo.$t)
// email /p:person/c:contactInfo/email/text()
alert("email =" + doc.person.contactInfo.email.$t);
// (compare to doc.p$person.c$contactInfo.email.$t)
var i;
for (i=0; i < doc.person.contactInfo.phone.length; i++) {
alert( "phone " + i + "=" + doc.person.contactInfo.phone[i].$t);
}
One advantage of using the non-prefixed method when dealing with JSON representations is that you do not have to determine the actual prefix bound to the element at runtime to access element properties. So, instead of doc.ns1$person.ns5$contactInfo.email.type, you can use doc.person.contactInfo.email.type.
Restrictions on JSON Representation of XML Content
The following restrictions exist for JSON representation of XML content:
- •Mixed types are not supported.
- •Element text nodes that contain only whitespace characters (including tabs, line feeds, and the like) are not serialized into JSON, since in general, these artifacts are due to pretty printing XML.
- •For the XML document that uses prefixes, you must assign a unique prefix for each namespace rather than overloading a prefix to multiple namespaces.
<!-- Prefix 'p' is initially used for ns urn:ns:person. -->
<p:person xmlns:p="urn:ns:person">
<!-- Prefix 'p' is re-used in contactInfo in a different ns.
Avoid this case. -->
<p:contactInfo xmlns:p="urn:ns:contactinfo" type="home" default="true" >
</p:contactInfo>
</p:person>
- •Elements or attributes names should follow standard rules for naming JavaScript variables. For example, do not use any punctuation marks of any kind in element (or attribute) names other than the underscore. For example, <first-name> is not allowed because it has a hyphen(-) in it name).
- •Avoid attributes or elements names that are reserved words in JavaScript. See https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Reserved_Words for more information.
- •Avoid elements or attributes named length.
- •Avoid having an element whose attributes and child elements have the same name. For example:
<contactInfo xmlns="urn:ns:contactinfo" type="home" default="true" >
<!-- Note 'type' is an attribute (of contactInfo) as well as a
child element. Avoid this case. -->
<type>foo</type>
<phone type="voice">203-555-1212</phone>
<phone type="fax">203-555-1213</phone>
<email xmlns="">jsmith@example.com</email>
</contactInfo>
Using AE_JSON_NODE_UTIL JavaScript library
The AE_JSON_NODE_UTIL JavaScript object provided by the ae-avc-util.js script file included with this SDK has helper functions that you can use when working with JSON representation of XML data.
Function | Description |
---|
AE_JSON_NODE_UTIL.getElements( aJsonObject) | Returns JSON objects in an array. Use this when the JSON object represents a repeating element. var phones = AE_JSON_NODE_UTIL.getElements( doc.person.contactInfo.phone); // phones is an array.
|
AE_JSON_NODE_UTIL.getText( aJsonObject, aDefaultText) | Returns the text value (the value of $t property) given the JSON object. If the text node does not exist, the default string value is returned. // get first number or return "Not Available" if number does not exist. var phones = AE_JSON_NODE_UTIL.getElements(doc.person.contactInfo.phone); // phone_number is 203-555-1212. var phone_number = AE_JSON_NODE_UTIL.getText(phones[0], "Not Available");
|
AE_JSON_NODE_UTIL.isXsiNil( aJsonObject) | Returns true if the aJsonObject element exists and it is XSI nulled. |
AE_JSON_NODE_UTIL.getAttribute( aJsonObj, aAttributeName, aDefault) | Returns attribute value given its name. If the attribute does not exist, the default value is returned. Normally you do not have to use this function as you can directly access JSON properties (attributes). This method is useful if your XML has a case where an element child and attribute have the same name (see restrictions above). // get list of phones var phones = AE_JSON_NODE_UTIL.getElements(doc.person.contactInfo.phone); // get phone type (voice, fax etc.) var phone_type = AE_JSON_NODE_UTIL.getAttribute(phones[0], "type", "Not Available"); // phone_type is 'voice'.
|