Foundation · Documents as sequences

Invercargill-Json

JSON support for Invercargill: a document becomes an Enumerable collection that queries and transforms like any other sequence. Json-glib does the parsing; this library gives its nodes the interface the rest of the stack speaks.

Version
0.1
Licence
LGPL-3.0-or-later
Package
usm install invercargill-json
Language
Vala

Overview

A compact companion

Invercargill-Json provides JSON functionality to Invercargill — that single sentence is the library's whole README, and it is an honest measure of the project's scope. This is a compact companion library, not an exercise in surface area: five small source files that wrap json-glib's nodes in Invercargill types so a JSON document answers the same queries as a database result or a settings file.

Its worth shows up in the stack above it: Statum's signed state slots serialise through it, and the fixes it carries — integers serialising as JSON numbers rather than boxed strings, large int64 values round-tripping without precision loss — were found in exactly that downstream path.

Features

What it hands you

  • JsonElement. One element type for any node, parsed from a string, a file or a stream — including an async stream variant.
  • Typed access. assert_as<T> and try_get_as<T> turn nodes into the Vala types you actually wanted.
  • Queryable documents. Arrays and objects are Enumerable: filter, project, aggregate and order a document with the same calls as any sequence.
  • JsonElements promotions. as_strings(), as_integers(), as_doubles(), as_bools(), as_objects(), as_property_groups() project a node sequence straight onto typed values.
  • JSON Lines. Stream .jsonl in and out through JsonlInputStream and JsonlOutputStream, one element at a time.
  • Objects as Properties. A JsonObject is an associative Enumerable of key-value pairs, so property mapping works on documents too.

Installation

Getting the library

Install the foundation first, then this companion:

usm install invercargill
usm install invercargill-json
USM resolves the invercargill-1 and json-glib dependencies itself.

From source:

git clone <the Invercargill-Json repository>
cd Invercargill-Json
meson setup build
ninja -C build
ninja -C build install
Meson and ninja are the only build tools needed.
valac --pkg invercargill-json my-program.vala
The binding pulls in its .deps chain automatically.

Usage & documentation

Reading documents as sequences

Parse, assert the shape, project to types — the library's own tests read like documentation:

using Invercargill;
using InvercargillJson;

var json_str = """[
    "Glengarry",
    "Gladstone",
    "Strathern",
    "Richmond",
    "Georgetown"
]""";

var suburbs = new JsonElement.from_string(json_str)
    .assert_as<JsonArray>()
    .as_strings()
    .to_array();
// suburbs.length == 5, suburbs[0] == "Glengarry"
From src/tests/Integration/Json.vala — a document becomes a typed Vala array in four calls.

Objects read by key, with nullable getters that tell you what is actually there:

var obj = new JsonElement.from_string("""
    { "name": "Aurora", "age": 27, "active": true }
""").assert_as<JsonObject>();

string? name    = obj.get_string("name");
int64?  age     = obj.get_integer("age");
bool?   active  = obj.get_bool("active");
double? height  = obj.get_double("height");   // null — absent keys answer null
From src/lib/Object.vala — get_array, get_object, try_get and has complete the set.

Because documents are Enumerables, the whole modifier vocabulary applies. Select the fields you want from every record in an array of objects; filter objects on their contents; hand the result to anything that consumes a sequence.

Scalars and whole classes map onto the same representation:

// A GObject property becomes a JSON number, faithfully
var v = Value(typeof(int64));
v.set_int64(99);
var j = new JsonElement.from_element(new ValueElement(v));
assert(j.stringify() == "99");
From src/tests/Integration/FromElement.vala — the regression tests for scalar dispatch, including int64 precision at 2⁵³ + 1.

For line-delimited streams — logs, exports, model output — the JSON Lines classes keep memory flat:

// Reading: one element at a time, or as a lazy Enumerable
var input = new JsonlInputStream.from_file(File.new_for_path("events.jsonl"));
JsonElement? element = input.read_next();

// Writing
var output = new JsonlOutputStream(stream);
output.write(element);
output.write_all(elements);
From src/lib/Jsonl.vala.

Package & source

The ledger

Version
0.1 (from MANIFEST.usm)
Licence
LGPL-3.0-or-later — free to run, study, share and improve; the LGPL keeps it free to link from any program.
Package
usm install invercargill-json
Provides
libinvercargill-json.so, invercargill-json.h, invercargill-json.vapi + .deps, invercargill_json-1.0.gir, invercargill_json-1.0.typelib, invercargill-json.pc
Needs at runtime
GLib, GObject, Gio, json-glib, and libinvercargill-1.so — its reason for being.
Source
The repository Tilo15/Invercargill-Json on the Astrologue forge (git over ssh, port 222). Free software: the licence guarantees your right to the source.