JSON-query'ish meta language for iRules

Intro

Jason Rahm recently dropped his "Working with JSON data in iRules" series, which included a few JSON challenges and a subtle hint  [string toupper [string replace Jason 1 1 ""]] about the upcoming iRule challenge at AppWorld 2026 in Las Vegas. With cash prizes and bragging rights on the line, my colleagues and I dove into Jason's code. While his series is a great foundation, we saw an opportunity to push the boundaries of security, performance and add RFC compliance.

Problem

Although F5 recently introduced native iRule commands for JSON parsing (v21.x); these tools remain "bare metal" compared to modern programming languages.

They offer minimal abstraction, requiring developers to possess both deep JSON schema knowledge and advanced iRule expertise to implement safely. Without a supporting framework, engineers are forced to manually manage complex types, nested objects, and arrays. A process that is both labor-intensive and error-prone.

As JSON has become the de facto standard for AI-centric workloads and modern API traffic, the need to efficiently manipulate session data on the ADC platform has never been greater.

Solution

Our goal is to bridge this gap by developing a "Swiss Army Knife" framework for iRule JSON parsing, providing the abstraction and reliability needed for high-performance traffic management.

Imagine a JSON data structure as shown below:

{
	"my_string": "Hello World",
	"my_number": 42,
	"my_boolean": true,
	"my_null": null,
	"my_array": [
		0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
	],
	"my_object": {
		"nested_string": "I'm nested"
	},
	"my_children": [
		{"name": "Anna Conda","firstname": "Anna", "surname": "Conda"},
		{"name": "Justin Case","firstname": "Justin", "surname": "Case"},
		{"name": "Don Key","firstname": "Don", "surname": "Key"},
		{"name": "Artie Choke","firstname": "Artie", "surname": "Choke"},
		{"name": "Barbie Doll","firstname": "Barbie", "surname": "Doll"}
	]
}

The [call json_get] and [call json_set] procedures from our iRule introduce a JSON-Query meta-language to slice information into and out of JSON. Here are a few examples of how these procedures can be used:

# Define JSON root element

set root [JSON::root]

# Without a filter is behaves like json_stringify

log [call json_get $root ""]
-> {"my_string": "Hello World","my_number": 42,"my_boolean": true,"my_null": .... <truncated for better readability>

# But as soon as you add filters, it becomes parsing on steroids!

log [call json_get $root "my_string"]
-> "Hello World"

# You simply ask for a path and you promptly get an answer!

log [call json_get $root "my_object nested_string"]
-> "I'm nested"

# Are you ready for the more advanced examples?

log [call json_get $root "my_array (5)"]
-> [5]

log [call json_get $root "my_array (0,5-10,16-18)"]
-> [0,5,6,7,8,9,10,16,17,18]

log [call json_get $root "my_children (*) firstname"]
-> ["Anna","Justin","Don","Artie","Barbie"]

log [call json_get $root "my_children (*) {firstname|surname}"]
-> [["Anna","Conda"],["Justin","Case"],["Don","Key"],["Artie","Choke"],["Barbie","Doll"]]

# Lets add some information to my childrens...

call json_set $root "my_children (0,4) gender" string "she/her"
call json_set $root "my_children (1-3) gender" string "he/him"
call json_set $root "my_children (2) gender" string "they/them"
log [call json_get $root "my_children (*) name|gender"]
-> [["Anna Conda","she/her"],["Justin Case","he/him"],["Don Key","they/them"],["Artie Choke","he/him"],["Barbie Doll","she/her"]]

# Lets write in an empty cache...

set empty_cache [JSON::create]
call json_set $empty_cache "rootpath subpath" string "I'm deeply nested"
log [call json_get $empty_cache]
-> {"rootpath": {"subpath": "I'm deeply nested"}}

After seeing what our project is about, lets try how [call json_get] and [call json_set] can be used to solve the challenges Jason suggested in his Working with JSON data in iRules series.

As a reminder, this is Jason's final iRule with his open challenges to the community:

when JSON_REQUEST priority 500 {
	set json_data [JSON::root]
	if {[call find_key $json_data "nested_array"] contains "b" } {
		set cache [JSON::create]
		set rootval [JSON::root $cache]
		JSON::set $rootval object
		set obj [JSON::get $rootval object]
		JSON::object add $obj "[IP::client_addr] status" string "rejected"
		set rendered [JSON::render $cache]
		log local0. "$rendered"
		HTTP::respond 200 content $rendered "Content-Type" "application/json"
	}
}

"Now, I offer you a couple challenges.

lines 4-9 in the JSON_REQUEST example above should really be split off to become another proc, so that the logic of the JSON_REQUEST is laser-focused. How would YOU write that proc, and how would you call it from the JSON_REQUEST event?

The find_key proc works, but there's a Tcl-native way to get at that information with just the JSON::object subcommands that is far less complex and more performant. Come at me!"
-Jason Rahm

By using our general-purpose iRule procedures, we achieve the laser-focused syntax Jason requested:

when JSON_REQUEST priority 500 {
	set json_data [JSON::root]
	if { [call json_get $json_data "my_object nested_array"] contains "b" } then {
		set cache [JSON::create]
		call json_set $cache "{[IP::client_addr] status}" string "rejected"
		HTTP::respond 200 content [JSON::render $cache] "Content-Type" "application/json"
	}
}

Despite our larger codebase, it is remarkable that our code runs ~20% faster (425 vs. 532 microseconds) per JSON request. This performance gain stems from traversing the JSON structure with a provided path; the procedure knows exactly where to look without unnecessary searching. Additionally, we utilized performance-oriented syntax that prefers fast commands, deploys variables only when necessary, and avoids string-to-list conversions (Tcl shimmering).

Impact

Our project highlights the current state of JSON-related iRule commands and proves that meta-languages are more suitable for the average iRule developer.

We hope this project catches the attention of F5 product development so that a similar JSON-query language can be provided natively.

In the meantime, we are deploying this code in production environments and will continue to maintain it.

Code

Because of size restrictions we had to attach the code as a file.

Installation

  1. Upload the submitted iRule code to your BIG-IP, save as new iRule.
  2. Attach a JSON profile to your virtual server.
  3. Then attach the iRule to this virtual server.
  4. Ready for testing, enjoy!

Demo Video Link

https://youtu.be/wAHjeC-j8MM 

Published Mar 10, 2026
Version 1.0
No CommentsBe the first to comment