Welcome to follow the official wechat account: FSA Full Stack Action 👋
Jsonnet: Google’s JSON data template language.
Features: Support for comments, references, arithmetic, conditional operators, array and object inclusion, introduction, functions, local variables, inheritance, etc.
- Website: jsonnet.org
- GitHub:github.com/google/json…
- Example official language: github.com/google/json…
A, install,
brew install jsonnet
Copy the code
Second, the tool
VSCode
- Plug-in:
Jsonnet NG
: Supports syntax highlighting and saves previews
After installing the plug-in, click the preview button in the upper right corner
The default preview result is yamL. You can search for jsonnet Preview in Settings to find the corresponding setting and select JSON.
Three, characteristics
1, field,
define
Field names can be unquoted, but must be quoted if there are Spaces
{
field1: 'lxf1',
"field 2": 'lxf2'
}
Copy the code
Hidden fields
The fields defined are not output to the JSON result
Language :: 'jsonnet', LXF: {lang: $. Language, author: name}}Copy the code
Results:
{
"lxf": {
"author": "LXF"."lang": "jsonnet"}}Copy the code
2, comments,
Single line comments// Single-line comments
/* Multi-line comments */
Copy the code
3. String
quotes
Single quotes are no different from double quotes
A single line verbatim string
# Single-line verbatim strings: use @{"single line": @'hello \ lxf'
}
Copy the code
Results:
{
"single line": "hello \\ lxf"
}
Copy the code
Multiline verbatim string
# multi-line string word by word: use | | | {"multiple line": |||
hello
lxf
|||,
}
Copy the code
Results:
{
"multiple line": "hello\nlxf\n"
}
Copy the code
Joining together
{
pi:: 3.1415926,
format: 'Hello, %s' % 'lxf',
concat: 'Hello, ' + 'lxf',
format1: |||
hello
pi=%(pi)0.2f
||| % self,
}
Copy the code
Results:
{
"concat": "Hello, lxf"."format": "Hello, lxf"."format1": "Hello \ npi = 3.14 \ n"
}
Copy the code
4, variables,
define
- use
local
The keyword defines a variable - Variables defined next to fields are marked with commas (
.
), other cases define variables with a semicolon (;
) at the end
local github = 'https://github.com/LinXunFeng'; Variables that are not defined next to fields end in a semicolonLanguage :: 'jsonnet', LXF: {target: $. Language, author: name, by: self.author, address: github } }Copy the code
Results:
{
"lxf": {
"address": "https://github.com/LinXunFeng"."author": "LinXunFeng"."by": "LinXunFeng"."target": "jsonnet"}}Copy the code
reference
- Variable name: Proximity principle
self
Keyword: Point to the current object$
Keyword: Point to the root object[' field name ']
: is used to find a fieldThe field name
: Fetch a field, but the field name must conform to the normal naming standard (cannot start with a number, cannot contain Spaces, etc.).[number]
: Is used to fetch array elements- Allowed long path
- Strings and arrays allow images
python
Use array slices likearr[10:20:2]
local github = 'https://github.com/LinXunFeng';
{
local name = 'LXF',
language:: 'jsonnet',
lxf: {
target: $.language,
author: name,
by: self.author,
address: github,
languages: ['oc', 'swift', 'python'],
nums: [1.8.11.22.33.44.55],
},
lqr: {
local name = "fsa_fullstackaction",
languages: ['java', 'kotlin', 'python'],
scores: $.lxf.nums[1:3],
organization: name[4:],
height: $['lxf'].nums[0] + 'm'
},
}
Copy the code
Results:
{
"lqr": {
"height": "1.8 m"."languages": [
"java"."kotlin"."python"]."organization": "fullstackaction"."scores": [
11.22]},"lxf": {
"address": "https://github.com/LinXunFeng"."author": "LXF"."by": "LXF"."languages": [
"oc"."swift"."python"]."nums": [
1.8.11.22.33.44.55]."target": "jsonnet"}}Copy the code
5. Four operations
- Support four operations, bit operations, comparison logic
+
When a string is encountered in the operation, the numeric value is converted to a string for concatenation- Strings can be compared
- use
in
Keyword to determine whether a field in the specified object
{
info: {
name: 'LinXunFeng'
},
ex1: (1 + 2) / 3 * 4,
ex2: 1 << 2,
ex3: 'a' <= 'b',
ex4: 'a' == 'b',
ex5: 5 + 6 + '1'+1,
ex6: 'name' in self.info,
}
Copy the code
Results:
{
"ex1": 4."ex2": 4."ex3": true."ex4": false."ex5": "1111"."ex6": true."info": {
"name": "LinXunFeng"}}Copy the code
6, functions,
- Support for positional, named, and default parameters
- Support closures
- A number of commonly used functions are already defined in Standard Library
local addNumber(number) = function(x) number + x;
local add2 = addNumber(2);
local add3 = addNumber(3); {# closures: closures: [add2(2),
add3(5Local sayHello(name) =' hello %s' % name, sum(x, y):: x + y, newPerson(name=' LXF ', age=18, gender='male'):: {name: name, age: age, gender: gender,}, # call call_say_hello: sayHello(' LXF '), call_sum: $.sum(1, 2),
lxf: $.newPerson(age=3),
standard_lib: std.join(' ', std.split('foo/bar', '/')),
len: [
std.length('hello'),
std.length([1.2.3])],}Copy the code
Results:
{
"call_say_hello": "hello lxf"."call_sum": 3."closures": [
4.8]."len": [
5.3]."lxf": {
"age": 3."gender": "male"."name": "lxf"
},
"standard_lib": "foo bar"
}
Copy the code
7. Conditional statements
Expression: if a then b else C, else is optional, returns null by default
local Person(isFemale) = {
name: 'lxf',
age: 18,
gender: if isFemale then 'female' else 'male',
[if isFemale then 'clothing']: 'dress',
};
{
condition1: if 2 > 1 then 'true' else 'false',
condition2: if 2 < 1 then 'true',
male: Person(false),
female: Person(true),}Copy the code
Results:
{
"condition1": "true"."condition2": null."female": {
"age": 18."clothing": "dress"."gender": "female"."name": "lxf"
},
"male": {
"age": 18."gender": "male"."name": "lxf"}}Copy the code
8. Object merge
- use
+
Operator to combine two objects, and if a field conflict is encountered, the fields in the object on the right are used - Right object can be used
super
Keywords refer to fields in the left object - use
+ :
When the operator combines two objects, the right object overwrites the existing fields in the left object, and the missing fields are added
# +
local base = {
f: 2,
g: self.f + 100}; base + { f:5,
old_f: super.f,
old_g: super.g,
}
##################################
# +:
local base = {
override: {
x: 1,
},
composite+: {
x: 1,}}; { override: { y:2,
z: 3
},
composite: {
y: 4,
z: 5
},
} + base
Copy the code
Results:
# +
{
"f": 5."g": 105."old_f": 2."old_g": 105
}
##################################
# +:
{
"composite": {
"x": 1."y": 4."z": 5
},
"override": {
"x": 1}}Copy the code
9. Import the template
- Similar to copy/paste code
- It can also be used to import
json
The original data - The suffix of a template file must be
.libsonnet
- use
import
Keyword to import the template content and store it using the specified variable
Content of the template
{
newPerson(
name,
country='China',
age=18
):: {
name: name,
country: country,
age: age,
belly: [],
eat(food):: self + {
belly+: [food],
},
},
}
Copy the code
Use the template
Localpersontemplate = import 'libs/lxflib.libsonnet'; libsonnet = libsonnet; personTemplate .newPerson(name='lxf', age=3)
.eat('rice')
.eat('pear')
Copy the code
Results:
{
"age": 3."belly": [
"rice"."pear"]."country": "China"."name": "lxf"
}
Copy the code
Four, terminal use
1, basic use
#Simple code can be run directly using -e
jsonnet -e '{key: 1+2}'
Copy the code
View the conversion results of the Jsonnet file
jsonnet shuttle.jsonnet
Copy the code
2. Specify the library path
If there is an imported template file in the Jsonnet file, but only write the name of the template file, not the path
Libsonnet local personTemplate = import 'lxflib.libsonnet';Copy the code
In this case, direct execution of the command will report an error
RUNTIME ERROR: couldn't open import "lxflib.libsonnet": no match locally or in the Jsonnet library paths.
Copy the code
At this point you have two choices
Option 1: Honestly write the full relative path when importing
local personTemplate = import 'libs/lxflib.libsonnet';
Copy the code
Option 2: Use the -j
parameter
jsonnet -J ./libs shuttle.jsonnet
Copy the code
3. Export the result to a file
Export json files using jsonnet files
jsonnet shuttle.jsonnet -o shuttle.json
Copy the code
4. Multiple file output
Jsonnet also supports scenarios where multiple JSON files are generated using a single Jsonnet file, such as both A.JAXon and B.JAXon
{
"a.json": {
x: 1,
y: $["b.json"].y,
},
"b.json": {
x: $["a.json"].x,
y: 2,}}Copy the code
The command
#Jsonnet -m
Jsonnet file
jsonnet -m . multiple_output.jsonnet
Copy the code
Results:
$ cat a.json
{
"x": 1,
"y": 2
}
$ cat b.json
{
"x": 1,
"y": 2
}
Copy the code
Five, the application of
In order to improve our work efficiency, it is often to organize and save some commonly used commands.
I do, for example, and use it with Shuttle, a shortcut menu that uses JSON to configure terminal commands.
As shown in the figure below, I added the command that triggers the remote Jenkins to package, but the remote build machine for some reason switches between two fixed IP addresses, so I added two, only the IP is different
However, in addition to the packaging function, other functions are related to the build machine IP, so once we add an IP, we have to change a lot of things, and also find that the command is the same, if one day the command is changed… ðŸ˜
So in cases like this, we need the help of Jsonnet to simplify things.
On the left of the image below, I’ve defined some common templates under the libs directory and put some constant configurations into the constant.libsonnet template file
In the shuttle. Jsonnet file, the entire shuttle configuration is defined
The good thing about this is that when the new person comes in and you need them to be able to step in immediately to pack and distribute, you just need to configure the Shuttle.
Configuring the Shuttle simply requires adjusting the constant.libsonnet file and executing one line of command!
jsonnet . shuttle.jsonnet -o ~/.shuttle.json
Copy the code