Skip to content

Latest commit

 

History

History

jsonnet

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 

Jsonnet

1. What is Jsonnet?

  • Jsonnet is a data templating language. These data templates are transfomered into JSON object using Jsonnet library or commandline tool.
  • As a language, Jsonnet is extension of JSON - a valid JSON object is always valid Jsonnet template.

2. Features (note)

Check out the full version.

2.1. Simplified for humans

{
    // Jsonnet example
    person1: {
        name: "Alice",
        welcome: "Hello " + self.name + "!",
    },
    person2: self.person1 { name: "Bob" },
}
  • Commenting (C-style and Python-style comment).
  • Object fields (the strings to the left of the color) don't have quotes.
  • Referencing - one part of the structure can refer to another part using self and super keywords.

2.2. Data operations

{
    foo: [1, 2, 3], # arithmetic
    bar: [x * x for x in self.foo if x >= 2], # conditionals
    baz: { ["field" + x]: x for x in self.foo }, # array comprehension, quite similar to Python
    obj: { ["foo" + "bar"]: 3 },
}

2.3. Local variable

  • Define a local variable using local keyword.
  • Local variables won't shown up in JSON output but fields they are assigned to will.
// outside the object, ends with ";"
local utils = import "myimport.jsonnet";
{
   // inside the object, ends with ","
   local my_var = "This variable is private",
   my_use: my_var

}

2.4. Modularity

  • It's possible to import both code and raw data from other files.
  • The import construct is like copy/pasting Jsonnet code (end with .libsonnet). Raw JSON can be imported this way too.
  • The importstr construct is for verbatim UTF-8 text.
// martinis.jsonnet
{
    "Vodka Martini": {
        ingredients: [
            { kind: "Vodka", qty: 2 },
            { kind: "Dry White Vermouth", qty: 1 },
        ],
        garnish: "Olive",
        served: "Straight Up",
    },
    Cosmopolitan: {
        ingredients: [
            { kind: "Vodka", qty: 2 },
            { kind: "Triple Sec", qty: 0.5 },
            { kind: "Cranberry Juice", qty: 0.75 },
            { kind: "Lime Juice", qty: 0.5 },
        ],
        garnish: "Orange Peel",
        served: "Straight Up",
    },
}

// bar_menu.jsonnet
{
    cocktails: import "martinis.jsonnet" + {
        Manhattan: {
            ingredients: [
                { kind: "Rye", qty: 2.5 },
                { kind: "Sweet Red Vermouth", qty: 1 },
                { kind: "Angostura", qty: "dash" },
            ],
            garnish: "Maraschino Cherry",
            served: "Straight Up",
        },
        Cosmopolitan: {
            ingredients: [
                { kind: "Vodka", qty: 1.5 },
                { kind: "Cointreau", qty: 1 },
                { kind: "Cranberry Juice", qty: 2 },
                { kind: "Lime Juice", qty: 1 },
            ],
            garnish: "Lime Wheel",
            served: "Straight Up",
        },
    }
}
  • Like Python, functions have positional keywords, named parameters and default arguments.
// This function returns an object. Although
// the braces look like Java or C++ they do
// not mean a statement block, they are instead
// the value being returned.
local Sour(spirit, garnish='Lemon twist') = {
  ingredients: [
    { kind: spirit, qty: 2 },
    { kind: 'Egg white', qty: 1 },
    { kind: 'Lemon Juice', qty: 1 },
    { kind: 'Simple Syrup', qty: 1 },
  ],
  garnish: garnish,
  served: 'Straight Up',
};

{
  'Whiskey Sour': Sour('Bulleit Bourbon',
                       'Orange bitters'),
  'Pisco Sour': Sour('Machu Pisco',
                     'Angostura bitters'),
}

2.5. Object-orientation

  • Objects extend other object.
  • The object composition operator +, which merges two objects, choosing the right hand side when fields collide.
  • The self keyword, a reference to the current object.
local Base = {
  f: 2,
  g: self.f + 100,
};

local WrapperBase = {
  Base: Base,
};

{
  Derived: Base + {
    f: 5,
    old_f: super.f,
    old_g: super.g,
  },
  WrapperDerived: WrapperBase + {
    Base+: { f: 5 },
  },
}

3. Jsonnet Cli

3.1. Installation

go get github.com/google/go-jsonnet/cmd/jsonnet

3.2. Examples

  • Evaluate a file:
# landingpage.jsonnet
{
  person1: {
    name: 'Alice',
    welcome: 'Hello ' + self.name + '!',
  },
  person2: self.person1 { name: 'Bob' },
}
$ jsonnet landingpage.jsonnet

{
   "person1": {
      "name": "Alice",
      "welcome": "Hello Alice!"
   },
   "person2": {
      "name": "Bob",
      "welcome": "Hello Bob!"
   }
}
  • Evaluate a snippet:
$ jsonnet -e '{ x: 1 , y: self.x + 1 } { x: 10 }'

{
   "x": 10,
   "y": 11
}
  • Multiple file output: generate multiple JSON files from a single Jsonnet file.
// multiple_output.jsonnet
{
  "a.json": {
    "x": 1,
    "y": $["b.json"].y
  },
  "b.json": {
    "x": $["a.json"].x,
    "y": 2
  }
}
$ jsonnet -m . multiple_output.jsonnet
a.json
b.json
$ cat a.json
{
   "x": 1,
   "y": 2
}
$ cat b.json
{
   "x": 1,
   "y": 2
}
  • YAML Stream output:
// yaml_stream.jsonnet
local
  a = {
    x: 1,
    y: b.y,
  },
  b = {
    x: a.x,
    y: 2,
  };

[a, b]
 jsonnet -y . yaml_stream.jsonnet
---
{
   "x": 1,
   "y": 2
}
---
{
   "x": 1,
   "y": 2
}

4. Jsonnet style guide

Check out Databrick's repostiory.