Foundations.JSON

API Description
query Perform query on JSON data object
Schema.validate Validate a data object as valid JSON and, optionally, against a JSON schema object.
Schema.checkPropertyChange Checks an object property for a valid value given its schema.
Transformer.initialize Register a template for transforming JSON data objects.
Transformer.merge Merge two different JSON data objects.
Transformer.transform Transform JSON data object(s) according to a set of named transforms in a registered template.
Transformer.transformAndMerge Transform JSON data according to a set of named transforms in a registered template and merge it with other JSON data.

Including foundations.json in Your Code

To use foundations.json in your code:

You can then reference methods using standard dot notation. For example (Schema.validate):

Mojo.Log.info("FoundJSON: BadObj validate "+ JSON.stringify(fjson.Schema.validate(BadObj, jsonSchema)));


JSON.query

Performs a JSONQuery on a provided object and returns the results. This takes the form:

results = query(searchQuery, object);

If no object is provided (just a query), it returns a "compiled" function that evaluates objects according to the provided query. Compiled functions take the following form:

evaluator = query(searchQuery);
results = evaluator(object);  

JSONQuery provides a comprehensive set of data querying tools including filtering, recursive search, sorting, mapping, range selection, and powerful expressions with wildcard string comparisons and various operators. JSONQuery generally supersets JSONPath and provides syntax that matches and behaves like JavaScript where possible.

Supported Operators

JSONQuery evaluations begin with a provided object, which can be referenced with $. From the starting object, various operators can be successively applied, each operating on the result of the last operation.

You can explicitly begin your query with $, but it is not necessary, as it is implicitly auto-inserted. This allows you to start queries with operators. JSONQuery uses syntax that is similar to JavaScript (with a number of extra operators).

A simple query looks like this:

var data = {foo:"bar"};
var results = query("$.foo",data);
// results == "bar"

For the code samples in the table below, assume the following initializations and data structure:

var jsonlib = MojoLoader.require({name:"foundations.json", version: "1.0"});
var fjson = jsonlib["foundations.json"];
var ItemPrices = [{ "Item" : "drink", "price" : 2},
  { "Item" : "jacket", "price" : 22},
  { "Item" : "shoes", "price" : 17},
  { "Item" : "baseball", "price" : 6},
  { "Item" : "bat", "price" : 4},
  { "Item" : "book", "price" : 12}
  { "Item" : "BELL", "price" : 10}];

Operator Description Example/Output
.property

Returns the indicated object property, behaving exactly like JavaScript.

Mojo.Log.info("results = "+
               fjson.query(".foo",{foo:"bar"}));
results = bar
[expression] Returns the property name/index defined by the expression evaluation, behaving exactly like JavaScript. Get the value of Item for the second element:
Mojo.Log.info("FoundJSON : results = "+fjson.query("\[1\].Item", 
               ItemPrices));
results = jacket
[?expression] Returns array items matching the expression. This operator does not need to be in brackets, you can simply use ?expression, but without "containment", no operators can be used afterwards. Get elements whose price is greater than 7:
Mojo.Log.info("results = "+
               JSON.stringify(fjson.query("\[?price > 7\]",
               ItemPrices)));
results = [{"Item":"jacket","price":22},
           {"Item":"shoes","price":17},
           {"Item":"book","price":12},
           {"Item":"BELL","price":10}]
[^?expression] Same as [?expression] except that duplicate values/objects are removed from the result set  
[/expression], [], Indicates a sort operation ("/" = ascending and "" = descending). Multiple comma-delimited sort expressions are possible for multiple sort orders (first being highest priority), i.e., [/LastName,/FirstName].

Get items whose price is greater than 7, sort by Item:

Mojo.Log.info("results = "+
               JSON.stringify(fjson.query("\[?price > 7\]\[\/Item\]", 
               ItemPrices)));
results = [{"Item":"BELL","price":10},
           {"Item":"book","price":12},
           {"Item":"jacket","price":22},
           {"Item":"shoes","price":17}]
[=expression] Performs a map operation on an array, creating a new array with each item being the evaluation of the expression for each item in the source array. Create an array of prices from ItemPrices:
Mojo.Log.info("results = "+
               JSON.stringify(fjson.query("\[=price\]", 
               ItemPrices)));
results = [2,22,17,6,4,12,10]
[start:end:step] Performs an array slice/range operation, returning the elements from the optional start index to the optional end index, stepping by the optional step number. Get every other element:
Mojo.Log.info("results = "+
               JSON.stringify(fjson.query("\[0:7:2\]", 
               ItemPrices)));
results = [{"Item":"drink","price":2},
           {"Item":"shoes","price":17},
           {"Item":"bat","price":4},
           {"Item":"BELL","price":10}] 
[expr,expr] This a union operator, returning an array of all the property/index values from the evaluation of the comma delimited expressions.  
.* or [*] This returns the values of all the properties of the current object.  
$ This is the root object, If a JSONQuery expression does not being with a $, it will be auto-inserted at the beginning.  
@ This is the current object in filter, sort, and map expressions. Note that names are auto-converted to property references of the current object in expressions, but @ can be used for index access on the current object. The following queries are identical:
[?name='Fred']
[?@.name='Fred']
[?@['name']='Fred']
 
..property Performs a recursive search for the given property name, returning an array of all values with such a property name in the current object and any sub-objects.  
expr = expr Performs a comparison (like JS's ==). When comparing to a string, the comparison string may contain wildcards * (matches any number of characters) and ? (matches any single character). Get all Items beginning with lowercase "b":
Mojo.Log.info("results = "+
               JSON.stringify(fjson.query("\[?Item='b*'\]", 
               ItemPrices)));
results = [{"Item":"baseball","price":6},
           {"Item":"bat","price":4},
           {"Item":"book","price":12}]
expr ~ expr Compares strings without considering case.

Get all items that start with the letter b, regardless of case.

Mojo.Log.info("results = "+
           JSON.stringify(fjson.query("\[?Item~'b*'\]", ItemPrices)));
results = [{"Item":"baseball","price":6},
           {"Item":"bat","price":4},
           {"Item":"book","price":12},
           {"Item":"BELL","price":10}]
..[?expression] This will perform a deep search filter operation on all the objects and subobjects of the current data. Rather than only searching an array, this will search property values, arrays, and their children.  
$1,$2,$3, etc. These are references to extra parameters passed to the query function or the evaluator function.
Mojo.Log.info("results = "+
               JSON.stringify(fjson.query("\[?Item=$1 & price=$2\]", 
               ItemPrices,"book",12)));
results = [{"Item":"book","price":12}]

It can also be used in an evaluator function.

var evaluator = fjson.query("\[?Item=$1 & price=$2\]");
Mojo.Log.info("results = "+ 
      JSON.stringify(evaluator(ItemPrices,"book",12)));
results = [{"Item":"book","price":12}]
+, -, /, *, &, |, %, (, ), <, >, <=, >=, != These operators behave just as they do in JavaScript.  

Multiple operators can be used successively to create complex queries. For example, to find all the objects from the products array with a price less than 15, sorted in descending order by rating, and showing only the first three items from the resultant list, we could do this query:

//** Query = $.products[?price < 20][\rating][0:3]

var products = [{ "book" : "Color Purple", "price" : 21, "rating":8},
  { "book" : "Obama", "price" : 12, "rating":4},
  { "book" : "Pride and Prejudice", "price" : 17, "rating":6},
  { "book" : "Winnie the Pooh", "price" : 22, "rating":9},
  { "book" : "Crime and Punishment", "price" : 14, "rating":10},
  { "book" : "Brothers Karamazov", "price" : 12, "rating":9}
  { "book" : "Anna Karenina", "price" : 10}, "rating":8];

Mojo.Log.info("results = "+ JSON.stringify(fjson.query("\[?price < 20\]\[\\rating\]\[0:3\]", products)));
results = [{"book":"Crime and Punishment","price":14,"rating":10},
  {"book":"Brothers Karamazov","price":12,"rating":9},
  {"book":"Anna Karenina","price":10,"rating":8}] 

Queries can use the regular operators to form general expressions based on more complex query operations. For example, to find the difference between the lowest priced item and the highest priced item in an array:

$.store.book[\price][0].price – $.store.book[/price][0].price  

Syntax

    query( {search query}, {JSON object});

Parameters

Argument Required Type Description
query Yes string Search query.
JSON object No any JSON search object.

Returns

Results of query or "compiled" function.