JSLT
JSLT is a JSON templating and transformation engine. It enables developers to declaratively map, filter, and reshape JSON data using pure JSON templates, powered by JMESPath for data extraction and a safe, stack-based execution model.
📦 Installation
pip install jslt
🚀 Quick Start
import json
from jslt import JSLT
data = {
"users": [
{"name": "Alice", "age": 25, "score": 88.5},
{"name": "Bob", "age": 17, "score": 92.0}
],
"threshold": 18
}
template = {
# Extract only adult users
"adults": {
"jsl:each": {
"path": "users",
"template": {
"jsl:if": {
"test": "age >= root().threshold",
"then": {
"name": {
"jsl:path": "name"
}
}
}
}
}
},
# Extract only adult users using jmespath
"adults_jpath": {
"jsl:var": {
"name": "threshold",
"path": "threshold"
},
"jsl:each": {
"path": "users[?age>var('threshold')]",
"template": {
"name": {
"jsl:path": "name"
}
}
}
},
# Find names with score > 90
"top_scorers": {"jsl:path": "users[?score>`90`].name"},
# Calculate average score
"avg_score": {"jsl:eval": "round(sum(users['*'].score) / count(users), 2)"},
# Calculate average score using jmespath
"avg_score_jpath": {"jsl:path": "avg(users[*].score)"}
}
jslt = JSLT(template)
result = jslt.transform(data)
print(json.dumps(result, indent=2))
Output:
{
"adults": [
{
"name": "Alice"
}
],
"adults_jpath": [
{
"name": "Alice"
}
],
"top_scorers": [
"Bob"
],
"avg_score": 90.25,
"avg_score_jpath": 90.25
}
🔑 Core Features
- JMESPath Integration: Leverage full JMESPath syntax for powerful data extraction and filtering.
- Custom DSL Functions: Transform data using internal functions (
jsl:var,jsl:if,jsl:each,jsl:keep,jsl:eval,jsl:path). - Stack-Based Iteration: Uses an iterative stack engine to process templates, completely avoiding Python recursion limits.
- Safe Expression Evaluation: Math and logic expressions are evaluated securely via
simple_eval(), preventing arbitrary code execution.
📝 Template DSL & Syntax
Templates are standard JSON objects. Each key defines an output field, and its value contains transformation instructions.
🔹 JSL Functions
All operations are prefixed with jsl: (namespace).
Object keys are passed to the function as named parameters. If the value is an array, the values are used as positional parameters.
The engine provides the following functions:
| Function | Description |
|---|---|
jsl:var |
Store intermediate values for reuse |
jsl:if |
Conditional branching ([test, then, other]) |
jsl:each |
Iterate over arrays and apply child templates ([path, template]) |
jsl:keep |
Instructs the engine to keep this object, even if it resolves to None |
jsl:eval |
Evaluate arithmetic/logic expressions |
jsl:path |
Resolve a JMESPath |
🧭 JMESPath custom functions
Custom functions are injected into JMESPath to provide additional functionality:
- Context Helpers:
root()→ References the root nodeparent()→ Move up the data treecurrent()→ Reference the active nodevar()→ Gives access to previously defined variables
- Math:
multiply()→ Multiply all values
- Text
strip()→ Remove whitespace from string
𝑓 Developing custom DSL functions
To integrate custom functions you simply have to create a class inheriting from jslt.engine.functions.Functions
Each function defined within the class using the following naming convention will be registered as a custom function:
_{namespace}_{function_name}
namespace may contain only lowercase chars
function_name may only contain lowercase chars and underscores
The first parameter passed to each function will be the execution context of type JSLT.Context
The following parameters may be named parameters where each parameter will correspond to the value of the respective object key if the item is an object.
If the item is a list, each list item will be passed as a positional parameter.
A single value will be passed to the function as a positional parameter.
Within the template DSL you may call your custom functions using object keys in the format {namespace}:{function_name}
Example
Function code
from jslt.engine.functions import Functions
from jslt.engine.transform import JSLT
class CustomFunctions(Functions):
def _custom_decorate_string(ctx: JSLT.Context, value: str):
return f"### {value} ###"
Template
{
"root": {
"my_value": "some value",
"custom_value": {
"custom:decorate_string": "custom value"
}
}
}
Output*
{
"root": {
"my_value": "some value",
"custom_value": "### custom value ###"
}
}
📜 License
This project is licensed under the MIT License. See LICENSE for details.
Release files for JSLT 2.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| jslt-2.2.1.tar.gz | 10.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| jslt-2.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 24.6 kB
Release files / jslt-2.2.1.tar.gz
| Download URL | jslt-2.2.1.tar.gz |
|---|---|
| Size | 10.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b21718fa600d95be57aedabd9b9ed7e0e2155d92802b8f23ae28c7384b29e128
|
|
BLAKE2b-256 checksum How to use checksums |
1af3181d20baec36e0ad6b98c5c42d65d6355c448623e42c9c09ef39a2b02c52
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|
Release files / jslt-2.2.1-py3-none-any.whl
| Download URL | jslt-2.2.1-py3-none-any.whl |
|---|---|
| Size | 14.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8ed21876dcf061548809b9b91a996c6f0727086d4d2a1ffa3597d238dbec4b25
|
|
BLAKE2b-256 checksum How to use checksums |
0c6606a3f7dcd027e93b3e1220c7174e19f493b9654a837b2220620274000516
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.3
|