Skip to content

Repository files navigation

jsonata_dart

A pure Dart implementation of JSONata - the JSON query and transformation language.

pub package

Usage

import'package:jsonata_dart/jsonata_dart.dart';
voidmain() {
final data = {
'Account': {
'Name':'Firefly',
'Order': [
{'Product':'Hat', 'Price':9.99},
{'Product':'Shoes', 'Price':49.99},
]
}
};
// Path expressionsprint(Jsonata('Account.Name').evaluate(data)); // "Firefly"// Aggregationsprint(Jsonata(r'$sum(Account.Order.Price)').evaluate(data)); // 59.98// Transformationsprint(Jsonata('Account.Order.Product').evaluate(data)); // ["Hat", "Shoes"]// Custom functionsfinal expr =Jsonata(r'$double(value)');
expr.registerFunction(r'$double', (args, input, env) => (args[0] asnum) *2);
print(expr.evaluate({'value':21})); // 42// Variable bindingfinal expr2 =Jsonata(r'price * $tax');
expr2.bind(r'$tax', 1.1);
print(expr2.evaluate({'price':100})); // 110.0// Regular expressionsprint(Jsonata(r'$match("hello world", /\w+/)').evaluate({}));
// {"match": "hello", "index": 0, "groups": []}// Date/time functionsprint(Jsonata(r'$now()').evaluate({})); // Current ISO 8601 timestampprint(Jsonata(r'$fromMillis(1527152400000, "[D] [MNn] [Y]")').evaluate({})); // "24 May 2018"print(Jsonata(r'$toMillis("2018-05-24", "[Y]-[M01]-[D01]")').evaluate({})); // 1527120000000// Transform operator (function chaining)print(Jsonata(r'"hello" ~> $uppercase ~> $length').evaluate({})); // 5// Parent operator (access parent context)print(Jsonata(r'Account.Order.Product{`Product Name`: %.OrderID}').evaluate(data));
// Groups products by name with their parent order ID// Sort operatorprint(Jsonata(r'Account.Order.Price^($)').evaluate(data)); // [9.99, 49.99]// Focus operator (bind current item to variable)print(Jsonata(r'Account.Order@$o.Product.{ "product": Product, "orderId": $o.OrderID }').evaluate(data));
// Index bind operator (bind iteration index)print(Jsonata(r'Account.Order#$i.{ "index": $i, "product": Product }').evaluate(data));
}

Features

Implemented

  • Path expressions - Navigate JSON structures with dot notation
  • Predicates and filters - Filter arrays with [condition]
  • Wildcards - * and ** for matching
  • String functions - $string, $length, $substring, $substringBefore, $substringAfter, $uppercase, $lowercase, $trim, $pad, $contains, $split, $join, $replace, $match, $base64encode, $base64decode
  • Numeric functions - $number, $abs, $floor, $ceil, $round, $power, $sqrt, $random, $formatNumber, $formatBase, $formatInteger, $parseInteger
  • Aggregation functions - $sum, $max, $min, $average, $count
  • Boolean functions - $boolean, $not, $exists
  • Array functions - $append, $count, $sort, $reverse, $shuffle, $distinct, $zip
  • Object functions - $keys, $values, $spread, $merge, $each, $sift, $type, $lookup
  • Higher-order functions - $map, $filter, $reduce, $sift, $each, $single
  • Regular expression functions - $match, $replace with regex, $contains with regex, $split with regex
  • Date/time functions - $now, $millis, $fromMillis, $toMillis with full XPath/XQuery picture string support
  • Transform operator - ~> for function chaining
  • Conditional expressions - Ternary ? : operator
  • Lambda expressions - function($x) { $x * 2 }
  • Variable binding - $variable := value
  • Partial application - Using ? placeholder
  • Custom functions - Register your own functions
  • Parent operator - % for accessing parent context in path expressions
  • Sort operator - ^(expr) for sorting arrays
  • Focus operator - @$var for binding current item to a variable
  • Index bind operator - #$var for binding iteration index to a variable

Not Yet Implemented

  • Async expressions

Differences from JavaScript JSONata

This is a clean-room Dart implementation, not a transpilation. Key differences:

AspectJavaScriptDart
UndefinedReturns undefinedReturns null (internally uses sentinel)
ExceptionsThrows with code, messageThrows JsonataException with same codes
Custom functionsexpr.registerFunction(name, fn, signature)expr.registerFunction(name, fn) (no signature validation)
AsyncSupports async expressionsSynchronous only

API

Jsonata(String expression)

Compiles a JSONata expression.

evaluate(dynamic data)

Evaluates the expression against JSON data. Returns the result or null if undefined.

registerFunction(String name, Function fn)

Registers a custom function. The function receives (List<dynamic> args, dynamic input, Environment env).

bind(String name, dynamic value)

Binds a variable for use in the expression.

ast

Returns the parsed AST for inspection.

Error Handling

try {
Jsonata('invalid[').evaluate({});
} onJsonataExceptioncatch (e) {
print('${e.code}: ${e.message}'); // S0302: Expected ']'
}

Error codes follow the JSONata specification.

License

MIT - see LICENSE

About

Pure Dart port of Jsonata (https://docs.jsonata.org/)

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages