uCalc API Version: 5.7.0-preview.1 Released: 7/30/2026

Warning

uCalc API Preview Release Notice:This preview documentation describes the intended behavior of the API. It is not fully accurate or complete.The current preview build contains incomplete features, unoptimized performance, and is subject to breaking changes.Use of the preview version in your production code is not recommended.

Project: Building a JSON Formatter and Minifier

Product: 

Class: 

A step-by-step project to build a simple parser for INI-style configuration files using the uCalc Transformer's hierarchical parsing capabilities.

Remarks

💡 Project: Building a JSON Formatter and Minifier

This project will guide you through building two essential tools for working with JSON: a formatter (or "pretty-printer") to make it human-readable, and a minifier to make it compact for transmission. It's a perfect real-world example of how the uCalc Transformer's token-aware, rule-based engine can parse and manipulate structured data formats.

The Goal

We'll create two transformers that can take a JSON string and convert it between these two formats:

Minified Input:{"id":123,"name":"Example","tags":["A","B"],"active":true}

Formatted Output:

{  "id": 123,  "name": "Example",  "tags": [    "A",    "B"  ],  "active": true}

💡 Why uCalc? (vs. Regex or a Dedicated JSON Library)

  • vs. Dedicated Libraries (Newtonsoft.Json, System.Text.Json): For production use, a dedicated, security-hardened JSON library is always the right choice. This project is an educational exercise to demonstrate how you would build a parser for a structured language. The principles learned here can be applied to any custom, non-standard format where a dedicated library doesn't exist.

  • vs. Regular Expressions: A regex-based approach would be extremely fragile. It would struggle to distinguish between a comma separating key-value pairs and a comma inside a string literal. uCalc's Transformer is token-aware. By default, it treats a quoted string as a single, unbreakable unit, making it safe and reliable for this task.


Step 1: The Formatter (Pretty-Printer)

The formatter's job is to insert newlines and indentation around structural tokens: {, }, [, ], ,, and :. To manage the indentation level, we need to maintain state during the transformation. This is a perfect use case for a uCalc variable controlled by {@Exec}.

The Strategy

  1. Create a uCalc variable named indent to track the current indentation level.
  2. Create a helper function IndentStr() to generate the indentation string.
  3. Define rules for each structural token to insert newlines and call IndentStr(), incrementing or decrementing the indent variable as needed.

Step 2: The Minifier

The minifier's job is much simpler: remove all non-essential whitespace. This includes spaces, tabs, and newlines that are not inside a string literal.

The Strategy

  1. Define a rule to find and remove all tokens categorized as {@Whitespace}.
  2. Define a second rule to find and remove all {@Newline} tokens.

Because the Transformer is QuoteSensitive by default, it will automatically protect any whitespace inside string values.

Let's see the complete implementation.

Examples

A complete JSON formatter that takes a minified string and pretty-prints it with proper indentation.

ID: 1382

				
					using uCalcSoftware;

var uc = new uCalc();
using (var t = new uCalc.Transformer(uc)) {
   // 1. Define state variable in the uCalc instance.
   uc.DefineVariable("indent = 0");

   // 2. Define the transformation rules.
   // Note: '{', '}', '[', ']' are escaped with quotes to be treated as literals.

   // Rule for '{' and '[': Add newline, increment indent, add indent string.
   t.FromTo("{ '{' | '[' }", "{@Self}{@nl}{@Exec: indent++}{@Eval: '  ' * indent}");

   // Rule for '}' and ']': Add newline, decrement indent, add indent string.
   t.FromTo("{ '}' | ']' }", "{@nl}{@Exec: indent--}{@Eval: '  ' * indent}{@Self}");

   // Rule for ',': Add newline and current indent string.
   t.FromTo(",", ",{@nl}{@Eval: '  ' * indent}");

   // Rule for ':': Add a space after it for readability.
   t.FromTo(":", ": ");

   // 3. Define the minified input string.
   var minifiedJson = """
{"id":123,"name":"Example","tags":["A","B"],"active":true}
""";

   // 4. Run the transformation and print the result.
   Console.WriteLine(t.Transform(minifiedJson));
}
				
			
{
  "id": 123,
  "name": "Example",
  "tags": [
    "A",
    "B"
  ],
  "active": true
}
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   {
      uCalc::Transformer t(uc);
      t.Owned(); // Causes t to be released when it goes out of scope
      // 1. Define state variable in the uCalc instance.
      uc.DefineVariable("indent = 0");

      // 2. Define the transformation rules.
      // Note: '{', '}', '[', ']' are escaped with quotes to be treated as literals.

      // Rule for '{' and '[': Add newline, increment indent, add indent string.
      t.FromTo("{ '{' | '[' }", "{@Self}{@nl}{@Exec: indent++}{@Eval: '  ' * indent}");

      // Rule for '}' and ']': Add newline, decrement indent, add indent string.
      t.FromTo("{ '}' | ']' }", "{@nl}{@Exec: indent--}{@Eval: '  ' * indent}{@Self}");

      // Rule for ',': Add newline and current indent string.
      t.FromTo(",", ",{@nl}{@Eval: '  ' * indent}");

      // Rule for ':': Add a space after it for readability.
      t.FromTo(":", ": ");

      // 3. Define the minified input string.
      auto minifiedJson = R"({"id":123,"name":"Example","tags":["A","B"],"active":true})";

      // 4. Run the transformation and print the result.
      cout << t.Transform(minifiedJson) << endl;
   }
}
				
			
{
  "id": 123,
  "name": "Example",
  "tags": [
    "A",
    "B"
  ],
  "active": true
}
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Using t As New uCalc.Transformer(uc)
         '// 1. Define state variable in the uCalc instance.
         uc.DefineVariable("indent = 0")
         
         '// 2. Define the transformation rules.
         '// Note: '{', '}', '[', ']' are escaped with quotes to be treated as literals.
         
         '// Rule for '{' and '[': Add newline, increment indent, add indent string.
         t.FromTo("{ '{' | '[' }", "{@Self}{@nl}{@Exec: indent++}{@Eval: '  ' * indent}")
         
         '// Rule for '}' and ']': Add newline, decrement indent, add indent string.
         t.FromTo("{ '}' | ']' }", "{@nl}{@Exec: indent--}{@Eval: '  ' * indent}{@Self}")
         
         '// Rule for ',': Add newline and current indent string.
         t.FromTo(",", ",{@nl}{@Eval: '  ' * indent}")
         
         '// Rule for ':': Add a space after it for readability.
         t.FromTo(":", ": ")
         
         '// 3. Define the minified input string.
         Dim minifiedJson = "{""id"":123,""name"":""Example"",""tags"":[""A"",""B""],""active"":true}"
         
         '// 4. Run the transformation and print the result.
         Console.WriteLine(t.Transform(minifiedJson))
      End Using
   End Sub
End Module
				
			
{
  "id": 123,
  "name": "Example",
  "tags": [
    "A",
    "B"
  ],
  "active": true
}
A complete JSON minifier that takes a formatted string and removes all non-essential whitespace.

ID: 1383

				
					using uCalcSoftware;

var uc = new uCalc();
using (var t = new uCalc.Transformer()) {
   // 1. Define rules to remove whitespace and newlines.
   // The engine's default QuoteSensitive=true ensures whitespace inside strings is protected.
   t.FromTo("{@Whitespace}", "");
   t.FromTo("{@Newline}", "");

   // 2. Define the formatted input string.
   var formattedJson = """
{
  "id": 123,
  "name": "Example, with spaces",
  "tags": [
    "A",
    "B"
  ]
}
""";

   // 3. Run the transformation and print the result.
   Console.WriteLine(t.Transform(formattedJson));
}
				
			
{"id":123,"name":"Example, with spaces","tags":["A","B"]}
				
					#include <iostream>
#include "uCalc.h"

using namespace std;
using namespace uCalcSoftware;

int main() {
   uCalc uc;
   {
      uCalc::Transformer t;
      t.Owned(); // Causes t to be released when it goes out of scope
      // 1. Define rules to remove whitespace and newlines.
      // The engine's default QuoteSensitive=true ensures whitespace inside strings is protected.
      t.FromTo("{@Whitespace}", "");
      t.FromTo("{@Newline}", "");

      // 2. Define the formatted input string.
      auto formattedJson = R"({
  "id": 123,
  "name": "Example, with spaces",
  "tags": [
    "A",
    "B"
  ]
})";

      // 3. Run the transformation and print the result.
      cout << t.Transform(formattedJson) << endl;
   }
}
				
			
{"id":123,"name":"Example, with spaces","tags":["A","B"]}
				
					Imports System
Imports uCalcSoftware
Public Module Program
   Public Sub Main()
      Dim uc As New uCalc()
      Using t As New uCalc.Transformer()
         '// 1. Define rules to remove whitespace and newlines.
         '// The engine's default QuoteSensitive=true ensures whitespace inside strings is protected.
         t.FromTo("{@Whitespace}", "")
         t.FromTo("{@Newline}", "")
         
         '// 2. Define the formatted input string.
         Dim formattedJson = "{
  ""id"": 123,
  ""name"": ""Example, with spaces"",
  ""tags"": [
    ""A"",
    ""B""
  ]
}"
         
         '// 3. Run the transformation and print the result.
         Console.WriteLine(t.Transform(formattedJson))
      End Using
   End Sub
End Module
				
			
{"id":123,"name":"Example, with spaces","tags":["A","B"]}