Skip to main content

· 6 min read

What is Jsonnet

Jsonnet is a Domain Specific Language (DSL) designed to simplify the creation, management, and maintenance of JSON data. It was originally designed and developed by Google employee Dave Cunningham as a 20% project around 10 years ago. The design of Jsonnet was influenced by several configuration languages used internally at Google, with the aim of improving the readability, maintainability, and programmability of configuration files while remaining compatible with JSON. It introduces features such as variables, functions, conditionals, loops, and code comments, making it easier and more intuitive to write complex data structures.

Jsonnet code is currently owned by Google. However, last month, due to the departure of Jsonnet's founder Dave Cunningham from Google for a new venture, the project is now managed by Rohit Jangid within Google.

What is KCL

KCL is an open-source, constraint-based record and functional language that enhances the writing of complex configurations, including those for cloud-native scenarios. It is hosted by the Cloud Native Computing Foundation (CNCF) as a Sandbox Project. With advanced programming language technology and practices, KCL is dedicated to promoting better modularity, scalability, and stability for configurations. It enables simpler logic writing and offers ease of automation APIs and integration with homegrown systems.

Differences Between Jsonnet and KCL

Design Philosophy

Jsonnet aims to enhance the readability and conciseness of configuration files through the introduction of programming language features such as variables, functions, operators, and control structures. This approach lowers the management complexity of complex configurations with guaranteed full compatibility with JSON. However, Jsonnet does not address important features such as types and validation, leading to a lack of consideration for stability and engineering efficiency in the configuration and policy domain.

At a design level, KCL is more "universal" and "modern", not only in its language design elements but also in its specific language features. Additionally, KCL focuses not only on simplifying the creation, management, and maintenance of JSON/YAML data, but also addresses specific cloud-native complexities and security risks. It converges language design towards problems specific to the cloud-native domain, aiming to converge its design around language technology and GitOps integration to strengthen stability and consistency guarantees. It achieves this through automated API, strong immutability, conflict detection, and support for custom validation expressions, among other capabilities.

Language Features

Both KCL and Jsonnet support variable definition, references, function definitions, and configuration merging, although their degrees of support and syntax semantics differ. They both support common programming language features such as arithmetic, logical operations, comprehensions, conditions, functions, standard libraries, and importing third-party modules, although in different manners. Unlike Jsonnet, KCL provides support for user-defined types, limited or mixed support for object-oriented features, and immutability, ensuring stability at an engineering level. Both KCL and Jsonnet can directly import JSON/YAML data types and Kubernetes CRDs.

Moreover, KCL integrates many built-in language features to fulfill configuration scenarios, such as configuration patching, data validation, and security compliance. This provides KCL with more static analysis capabilities to meet IDE or other tool chain needs and combine constraint checking.

Developer Tools

Both Jsonnet and KCL communities provide a wide range of language tools, including testing, formatting, and package management support. While Jsonnet's dynamic nature makes comprehensive IDE support difficult, KCL offers official Language Server support, which can be easily extended and integrated into IDE plugins, including NeoVim and other emerging LSP-supported IDEs or editors. KCL's Language Server provides complete features such as syntax highlighting, autocompletion, navigation, refactoring, and quick fixes, and is growing rapidly.

Multiple Language Bindings

For better integration of configuration language into users' applications, Jsonnet currently provides four different multi-language implementations in the community, including C++, Go, Rust, and Python bindings. KCL currently offers an official Rust implementation and provides various bindings such as Go, Python, Java, Node.js, C#, C++, C, and WASM, all based on Rust, ensuring predictable and consistent results regardless of the language used.

Performance

  • KCL (test.k)
a = lambda name: str {
apiVersion = "apps/v1"
kind = "Deployment"
metadata = {
name = name
labels = {"app": "nginx"}
}
spec = {
replicas = 3
selector.matchLabels = {"app": "nginx"}
template.metadata.labels = {"app": "nginx"}
template.spec.containers = [
{
name = metadata.name
image = "${metadata.name}:1.14.2"
ports = [{ containerPort = 80 }]
}
]
}
}
temp = {"a${i}": a("nginx") for i in range(1000)}
  • Jsonnet (test.jsonnet)
local a(name) = {
apiVersion: "apps/v1",
kind: "Deployment",
metadata: {
name: name,
labels: {["app"]: "nginx"}
},
spec: {
replicas: 3,
selector: {
matchLabels: {["app"]: "nginx"}
},
template: {
metadata: {
labels: {["app"]: "nginx"}
},
spec: {
containers: [
{
name: name,
image: name + ":1.14.2",
ports: [{ containerPort: 80 }]
}
]
}
},
}
};
{
temp: {["a%d" % i]: a("nginx") for i in std.range(0, 1000)},
}

Run time (considering actual resource expenditure in production environments, this test is based on a single core):

KCL v0.9.3Jsonnet v0.20.0 (C++ version)Jsonnet v0.20.0 (Go version)Jsonnet v0.5.0-pre96 (Rust version jrsonnet)Jsonnet v0.1.2 (Rust version rsjsonnet)
155 ms (kcl test.k)1480 ms (jsonnet test.jsonnet)400 ms (jsonnet test.jsonnet)153 ms (rsjsonnet test.jsonnet)142 ms (jrsonnet test.jsonnet)

Summary

The comparison table below summarizes the features of Jsonnet and KCL for reference.

FeaturesJsonnetKCL
Open Source LicenseApache-2.0Apache-2.0
Development LanguageC++, Go, Rust, etcRust
Language StyleJSON-likePython-like, Go-like
Language FunctionalityMediumHigh
Runtime PerformanceMediumMedium
Incremental Compilation
Standard Library
Package Management Tool
Formatting Tool
Documentation Tool
Testing Tool
Debugging Tool✅ (Simple ReplDebugger)
IDE PluginsIntelliJ, NeoVim, VS CodeIntelliJ, NeoVim, VS Code
Multi-language SDKsC++, Go, Python, RustGo, Python, Java, Node.js, C#, C++, C, WASM
Multi-language PluginsGo, Python, Java
Language Server
OCI Registry Support
Community Model Library
REST Server Support
Export Configuration DataJSON, YAML, TOML, ini, etc.JSON, YAML, TOML
Import from Other Data or Schema
Kubernetes Configuration Support
Cloud-native Tool Integration Support

References

· 9 min read

Introduction

The KCL team is pleased to announce that KCL v0.9.0 is now available! This release has brought three key updates to everyone

  • Enhance the coding experience and efficiency with a more performant, feature-rich, and less error-prone KCL language, toolchain, and IDE.
  • A more comprehensive and diverse set of standard libraries, third-party libraries, and community ecosystem integrations, covering different application scenarios and requirements.
  • Richer multi-language SDKs and plugins, seamlessly integrating with different programming languages and development environments.

KCL is an open-source, constraint-based record and functional language hosted by Cloud Native Computing Foundation (CNCF). KCL improves the writing of numerous complex configurations, such as cloud-native scenarios, through its mature programming language technology and practice. It is dedicated to building better modularity, scalability, and stability around configurations, simpler logic writing, faster automation, and great built-in or API-driven integrations.

❤️ Special Thanks

We would like to extend our heartfelt thanks to all 120 community contributors who participated in the iteration from version v0.8 to v0.9 over the past 120 days. The following list is in no particular order.

@Shashank Mittal, @MattHodge, @officialasishkumar, @Gmin2, @Akash Kumar, @sfshumaker, @sanzoghenzo, @MOHAMED FAWAS, @bradkwadsworth-mw, @excalq, @Daksh-10, @metacoma, @Wes McNamee, @Stéphane Este-Gracias, @octonawish-akcodes, @zong-zhe, @shashank-iitbhu, @NAVRockClimber, @AkashKumar7902, @Petrosz007, @patrycju, @Korada Vishal, @selfuryon, @tvandinther, @vtomilov, @Peefy, @taylormonacelli, @Tertium, @Stefano Borrelli, @Bishal, @kukacz, @borgius, @steeling, @jheyduk, @HStéphane Este-Gracias, @userxiaosi, @folliehiyuki, @kubernegit, @nizq, @Alexander Fuchs, @ihor-hrytskiv, @Mohamed Asif, @reedjosh, @Wck-iipi, @evensolberg, @aldoborrero@ron18219, @rodrigoalvamat, @mproffitt, @karlhepler, @shruti2522, @leon-andria, @prahaladramji, @Even Solberg, @utnim2, @warjiang, @Asish Kumar, @He1pa, @Emmanuel Alap, @d4v1d03, @Yvan da Silva, @Abhishek, @DavidChevallier, @zargor, @Kim Sondrup, @SamirMarin, @Hai Wu, @MatisseB, @beholdenkey, @nestoralonso, @HAkash Kumar, @olinux, @liangyuanpeng, @ngergs, @Penguin, @ealap, @markphillips100, @Henri Williams, @eshepelyuk, @CC007, @mintu, @M Slane, @zhuxw, @atelsier, @aleeriz, @LinYunling, @YvanDaSilva, @chai2010, @Sergey Ryabin, @vfarcic, @vemoo, @riven-blade, @ibishal, @empath-nirvana, @bozaro, @jgascon-nx, @reckless-huang, @Sergei Iakovlev, @Blarc, @JeevaRamanathan, @dennybaa, @PrettySolution, @east4ming, @nkabir, @sestegra, @XiaoK29, @ricochet1k, @yjsnly, @umaher, @SjuulJanssen, @wilsonwang371, @Lukáš Kubín, @samuel-deal-tisseo, @blakebarnett, @Uladzislau Maher, @ytsarev, @Vishalk91-4, @Stephen C, @Tom van Dinther, @MrGuoRanDuo, @dopesickjam

📚 Key Updates

⚡️ Performance Enhancements

Runtime Performance

In the new KCL v0.9 release, a new fast runtime mode has been introduced. This can be enabled by setting the KCL_FAST_EVAL=1 environment variable, which improves startup and runtime performance. For configurations using Schema (such as the k8s third-party library), this offers approximately a 3x performance boost compared to previous versions. For simple configurations without Schema, output YAML performance has been tested to surpass tools like helm template and kustomize build that use YAML and Go Templates.

IDE Performance

KCL IDE has further optimized incremental compilation and performance for semantic analysis in large projects. For KCL projects with around 400 files, the end-to-end response time has been reduced to 20% of the previous version.

🔧 Core Features

Language

  • String interpolation now supports escaping with \${} similar to Shell to cancel interpolation.
world = "world"
hello_world_0 = "hello ${world}" # hello world
hello_world_1 = "hello \${world}" # hello ${world}
  • Added schema type support to the typeof function for distinguishing schema types from instances.
schema Foo:
bar?: str

foo = Foo {}
type_schema = typeof(foo) # schema
type_type = typeof(Foo) # type
  • Added a full_pkg keyword argument to the instances() method of Schema to read instances of the corresponding schema from all code.
schema Person:
name: str

alice = Person {name = "Alice"}
all_persons = Person.instances(True)
  • Removed implicit comparison between bool and int types 0 < True.
  • Removed comparison features for the list type [0] < [1].
  • Added type assertion failure functionality to the as keyword.
  • Optimized closure variable capture logic of lambda functions and configuration code blocks {} in different scopes to be more intuitive.

Toolchain

  • kcl run now supports outputting configurations in TOML format with the --format toml option.
  • kcl mod add now supports adding dependencies from private third-party OCI Registries and Git repositories with the --oci and --git options.
  • kcl import now supports importing entire Go Packages as KCL Schemas.
  • kcl import now supports importing files with YAML stream format (---).
  • kcl import now supports importing TOML files as KCL configurations.
  • kcl clean now supports cleaning external dependencies and compile caches.
  • kcl mod init now supports setting the version of a new KCL module with the --version tag.
  • Commands like kcl run, kcl mod add, and kcl mod pull now support accessing private repositories via local Git.

IDE

  • Supports multiple quick fix options.
  • Syntax highlighting for kcl.mod and kcl.mod.lock files.
  • Partial syntax hover highlighting in the IDE.
  • import completion for external dependencies.
  • Function symbol highlighting and Inlay Hints displaying default variable types.

inlayhint

API

  • The Override API now supports setting different attribute operators (:, =, and +=) for configuration overrides.
  • Go API now supports prototext format and KCL schema output as KCL configurations.
  • Go API now supports serializing any Go Type and Go Value to KCL Schema and configurations.

📦️ Standard Libraries and Third-Party Libraries

Standard Libraries

  • Added the file standard library for file IO operations, such as reading configurations from YAML and performing configuration merges.
import file
import yaml
import json_merge_patch as p

config = p.merge(yaml.decode(file.read("deployment.yaml")), {
metadata.name = "override_value"
})

For more functions in the file module, see: https://www.kcl-lang.io/docs/reference/model/file

  • Added the template standard library for writing template configurations.
import template

_data = {
name = "handlebars",
v = [ { a = 1 }, { a = 2 } ],
c = { d = 5 },
g = { b = [ { aa = { bb = 55} }, { aa = { bb = 66} } ] },
people = [ "Yehuda Katz", "Alan Johnson", "Charles Jolley" ]
}

content = template.execute("""\
Hello world from {{name}}

{{#each v}}
{{this.a}}
{{/each}}
{{ c.d }}
{{#each people}}
{{ this }}
{{/each}}
{{#each g.b}}
{{this.aa.bb}}
{{/each}}
""", _data)
  • Added the runtime standard library for capturing runtime exceptions, useful for kcl test tool to test exception cases.
import runtime

schema Person:
name: str
age: int

check:
0 <= age <= 120, "age must be in [1, 120], got ${age}"

test_person_check_error = lambda {
assert runtime.catch(lambda {
p = Person {name = "Alice", age: -1}
}) == "age must be in [1, 120], got -1"
}

Third-Party Libraries

The number of KCL models has increased to 313, including major updates as follows:

  • k8s released version 1.30
  • argo-cd released version 0.1.1
  • argo-workflow released version 0.0.3
  • istio released version 1.21.2
  • victoria-metrics-operator released version 0.45.1
  • cert-manager released version 0.1.2
  • cilium released version 0.1.1
  • Longhorn released version 0.0.1
  • jsonpatch released version 0.0.5, supporting rfc6901Decode
  • Added a new third-party library difflib for comparing configuration differences
  • Added argo-cd-order for sorting argocd sync operation resource order
  • Added models for cluster-api, including cluster-api, cluster-api-provider-metal3, cluster-api-provider-gcp, cluster-api-addon-provider-helm, cluster-api-addon-provider-aws, cluster-api-provider-azure, and more

☸️ Ecosystem Integration

apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: example
spec:
compositeTypeRef:
apiVersion: example.crossplane.io/v1beta1
kind: XR
mode: Pipeline
pipeline:
- step: basic
functionRef:
name: function-kcl
input:
apiVersion: krm.kcl.dev/v1alpha1
kind: KCLInput
source: |
# Read the XR
oxr = option("params").oxr
# Patch the XR with the status field
dxr = oxr | {
status.dummy = "cool-status"
}
# Construct a AWS bucket
bucket = {
apiVersion = "s3.aws.upbound.io/v1beta1"
kind = "Bucket"
metadata.annotations: {
"krm.kcl.dev/composition-resource-name" = "bucket"
}
spec.forProvider.region = option("oxr").spec.region
}
# Return the bucket and patched XR
items = [bucket, dxr]
- step: automatically-detect-ready-composed-resources
functionRef:
name: function-auto-ready

Additionally, you can find more real use cases of KCL with other ecosystem projects here:

🧩 Multi-Language SDKs and Plugins

Multi-Language SDKs

The number of KCL multi-language SDKs has increased to 7, currently supporting Rust, Go, Java, .NET, Python, Node.js, and WASM. These can be used without installing additional KCL command-line tools, optimizing the installation size to 90% of previous versions and removing the need for complex system dependencies. Furthermore, each SDK provides the same APIs for code execution, code analysis, type parsing, and adding external dependencies. Here are some examples with the Java and C# SDKs:

  • Java
import com.kcl.api.API;
import com.kcl.api.Spec.ExecProgram_Args;
import com.kcl.api.Spec.ExecProgram_Result;

public class ExecProgramTest {
public static void main(String[] args) throws Exception {
API api = new API();
ExecProgram_Result result = api
.execProgram(ExecProgram_Args.newBuilder().addKFilenameList("path/to/kcl.k").build());
System.out.println(result.getYamlResult());
}
}
  • C#
namespace KclLib.Tests;

using KclLib.API;

public class KclLibAPITest
{
public static void Main()
{
var execArgs = new ExecProgram_Args();
execArgs.KFilenameList.Add("path/to/kcl.k");
var result = new API().ExecProgram(execArgs);
Console.WriteLine(result.YamlResult);
}
}

For more information on installing and using other SDKs, see https://github.com/kcl-lang/lib

Multi-Language Plugins

The number of KCL multi-language plugins has increased to 3, currently supporting Go, Python, and Java. Only basic SDK dependencies are required to achieve seamless interoperation between common languages and KCL. Here are some examples with Python and Java plugins:

Write the following KCL code (main.k)

import kcl_plugin.my_plugin

result = my_plugin.add(1, 1)

Use the Python SDK to register a Python function for calling in KCL

import kcl_lib.plugin as plugin
import kcl_lib.api as api

plugin.register_plugin("my_plugin", {"add": lambda x, y: x + y})

def main():
result = api.API().exec_program(
api.ExecProgram_Args(k_filename_list=["main.k"])
)
assert result.yaml_result == "result: 2"

main()

Use the Java SDK to register a Java function for calling in KCL

package com.kcl;

import com.kcl.api.API;
import com.kcl.api.Spec.ExecProgram_Args;
import com.kcl.api.Spec.ExecProgram_Result;

import java.util.Collections;

public class PluginTest {
public static void main(String[] mainArgs) throws Exception {
API.registerPlugin("my_plugin", Collections.singletonMap("add", (args, kwArgs) -> {
return (int) args[0] + (int) args[1];
}));
ExecProgram_Result result = new API()
.execProgram(ExecProgram_Args.newBuilder().addKFilenameList("main.k").build());
System.out.println(result.getYamlResult());
}
}

For more examples of using other multi-language plugins, see https://www.kcl-lang.io/docs/reference/plugin/overview

Additionally, you can find more real use cases of KCL multi-language plugins here:

🌐 Other Resources

🔥 Check out the KCL Community and join us 🔥

For more resources, refer to: