Open tfabacher opened 2 months ago
Yay go for it!
Interseting, you can implement it using Environment's getItem
argument or writing filter:
import 'dart:convert';
import 'package:jinja/jinja.dart';
import 'package:json_path/json_path.dart';
void main() {
var document = jsonDecode(_json);
print('All prices in the store, by JSONPath:');
JsonPath(r'$..price')
.read(document)
.map((match) => '${match.path}:\t${match.value}')
.forEach(print);
print('');
Object? getItem(Object? item, Object? object) {
if (object is Map<String, Object?> &&
item is String &&
item.startsWith(r'$')) {
return JsonPath(item)
.read(object)
.map<List>((match) => [match.path, match.value]);
}
try {
return (object as dynamic)[item];
} on NoSuchMethodError {
if (object == null) {
rethrow;
}
return null;
}
}
var filters = {
'jsonPath': (Object? document, Object? path) {
return getItem(path, document);
}
};
var environment = Environment(getItem: getItem, filters: filters);
print('All prices in the store, by getItem:');
var template = environment.fromString(_template);
print(template.render({'document': document}));
print('All prices in the store, by filter:');
var template2 = environment.fromString(_template2);
print(template2.render({'document': document}));
}
const _json = '''
{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
},
{
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
},
{
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}
''';
const _template = r'''
{% for path, price in document['$..price'] %}
{{- path }}: {{ price }}
{% endfor %}
''';
const _template2 = r'''
{% for path, price in document | jsonPath('$..price') %}
{{- path }}: {{ price }}
{% endfor %}
''';
Output:
All prices in the store, by Jinja:
$['store']['book'][0]['price']: 8.95
$['store']['book'][1]['price']: 12.99
$['store']['book'][2]['price']: 8.99
$['store']['book'][3]['price']: 22.99
$['store']['bicycle']['price']: 19.95
All prices in the store, by filter:
$['store']['book'][0]['price']: 8.95
$['store']['book'][1]['price']: 12.99
$['store']['book'][2]['price']: 8.99
$['store']['book'][3]['price']: 22.99
$['store']['bicycle']['price']: 19.95
One of the challenges with Jinja2 is that it does not support the JSON Path standard to query the JSON easily to get a value. It is easy to add to Python because it can simply be added, but there was no Dart conversion.
But now there is: https://github.com/f3ath/jessie https://pub.dev/packages/json_path
I think you will find Jinja MUCH MUCH easier and more powerful to use with JSON Path. We will try this with your great code and if you like the idea we can submit it to your main branch as a MR.
--Todd