JSON::Jsonnet
Perl XS bindings to libjsonnet (Google Jsonnet C/C++ API).
This module provides a thin, low-level interface to the official Jsonnet VM. You can evaluate Jsonnet snippets/files, use multi/stream outputs, and register custom import and native callbacks from Perl.
Requirements
This distribution requires libjsonnet (development headers and shared library).
You need:
libjsonnet.hlibjsonnet.so(or equivalent)- C++ standard library for linking (
libstdc++)
Jsonnet version 0.21.x or newer is recommended.
Debian / Ubuntu
sudo apt install libjsonnet-dev jsonnet
Fedora
sudo dnf install jsonnet jsonnet-devel
Arch
sudo pacman -S jsonnet
macOS (Homebrew)
brew install jsonnet
From source (if packages are unavailable)
git clone https://github.com/google/jsonnet.git
cd jsonnet
make libjsonnet.so
sudo cp include/libjsonnet.h /usr/local/include/
sudo cp libjsonnet.so /usr/local/lib/
sudo ldconfig # on Linux
Installation
Standard CPAN install
cpanm JSON::Jsonnet
If libjsonnet is in a non-standard prefix
Set JSONNET_PREFIX so the build can find headers and library:
JSONNET_PREFIX=/opt/jsonnet cpanm JSON::Jsonnet
or when building from the repo:
JSONNET_PREFIX=/opt/jsonnet perl Makefile.PL
make
make test
make install
The build will also try pkg-config libjsonnet automatically when available.
Usage
Basic evaluation
use JSON::Jsonnet;
my $vm = JSON::Jsonnet->new(
ext_vars => { foo => "bar" },
);
my $json = $vm->evaluate_snippet("snippet", '{ x: std.extVar("foo") }');
print $json;
Evaluate a file
my $json = $vm->evaluate_file("main.jsonnet");
print $json;
Multi output
Multi mode returns a hashref where keys are output filenames:
my $out = $vm->evaluate_file_multi("multi.jsonnet");
for my $name (sort keys %$out) {
print "== $name ==\n";
print $out->{$name};
}
Stream output
Stream mode returns an arrayref of JSON texts:
my $items = $vm->evaluate_snippet_stream("s", '[{a:1},{b:2}]');
for my $j (@$items) {
print $j;
}
Import callback
Register a custom importer. The callback must return:
($found_here, $content)on success(undef, $error_text)on failure
$vm->import_callback(sub {
my ($base, $rel) = @_;
# Example: virtual import
return ("virtual.jsonnet", '{ z: 42 }')
if $rel eq "virtual.jsonnet";
return (undef, "no such import: $rel");
});
my $json = $vm->evaluate_snippet("x", q'
local v = import "virtual.jsonnet";
{ z: v.z }
');
print $json;
Note: once you set import_callback, it replaces the default importer.
If you want filesystem imports too, implement them in your callback.
Native callbacks (std.native)
$vm->native_callback(
"add",
sub { my ($a, $b) = @_; $a + $b },
[qw(a b)],
);
print $vm->evaluate_snippet("n", 'std.native("add")(2, 3)');
Native callbacks accept primitive Jsonnet values (string/number/bool/null). Return values can be scalars, arrayrefs, hashrefs, or undef.
VM Options
You can set tuning parameters either via constructor or later:
my $vm = JSON::Jsonnet->new(
max_stack => 1000,
gc_min_objects => 10,
gc_growth_trigger => 2.5,
max_trace => 20,
string_output => 0,
);
$vm->jpath_add("./libsonnet");
$vm->ext_var("env", "prod");
$vm->tla_var("cfg", "value");
string_output => 1 makes top-level Jsonnet strings return without JSON quotes.
Troubleshooting
undefined symbol: jsonnet_make when loading the module
Your Jsonnet.so was built without linking to libjsonnet.
Fix by installing libjsonnet-dev or rebuilding with a correct prefix:
JSONNET_PREFIX=/path/to/jsonnet perl Makefile.PL
make clean
make
make test
Build cannot find libjsonnet.h
Install the development package (libjsonnet-dev, jsonnet-devel) or
provide JSONNET_PREFIX.
Import errors after setting import_callback
Setting an import callback replaces default imports. Handle filesystem imports yourself if needed.
License
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
Author
Sergey Kovalev info@neolite.ru