Jsson Docs
Patterns

Anti-Patterns

Common mistakes to avoid when writing JSSON configuration.

These are patterns that may work but lead to maintenance issues, performance problems, or confusing code. Avoid them.

Over-Engineering

Don't Use Logic for Static Data

If your data doesn't change, don't add unnecessary complexity.

//  Anti-pattern: Overcomplicating simple config
port := 8080
host := "localhost"
url = "http://" + host + ":" + port

//  Better: Just write the value
url = "http://localhost:8080"

Rule: Use logic when there's actual variation (environments, scale). Don't use it just because you can.


Don't Nest Maps Too Deep

Deeply nested maps become unreadable and hard to debug.

//  Anti-pattern: 4+ levels of nesting
result = (1..3 map (a) = (1..3 map (b) = (1..3 map (c) = (1..3 map (d) = {
  value = a + b + c + d
}))))

//  Better: Break into separate structures
grid [
  template { x, y }
  map (p) = { x = p.x, y = p.y, value = p.x + p.y }
  
  1, 1
  1, 2
  2, 1
  2, 2
]

Rule: If you need 3+ nested maps, rethink your data structure.


Presets Abuse

Don't Create Presets for One-Time Use

Presets are for reuse. If you only use it once, inline it.

//  Anti-pattern: Preset used exactly once
@preset "myServerConfig" {
  host = "api.example.com"
  port = 443
}
server = @use "myServerConfig" {}

//  Better: Just define it directly
server = { host = "api.example.com", port = 443 }

Rule: Create a preset only when you use it 2+ times.


Don't Override Everything

If you override most of the preset values, you're not benefiting from it.

//  Anti-pattern: Overriding 80% of preset
@preset "defaults" {
  timeout = 30
  retries = 3
  ssl = yes
  format = "json"
}

config = @use "defaults" {
  timeout = 60      // overridden
  retries = 5       // overridden
  ssl = no          // overridden
  path = "/api"
}

//  Better: Define a new preset or inline
config = {
  timeout = 60
  retries = 5
  ssl = no
  format = "json"
  path = "/api"
}

Rule: If you override more than half the values, it's not the right preset.


Validators Misuse

Don't Use Validators for Deterministic Data

Validators generate random data. Don't use them when you need specific values.

//  Anti-pattern: Random ID for production config
database {
  connectionId = @uuid  // Different every time!
}

//  Better: Use explicit values
database {
  connectionId = "db-primary-001"
}

Rule: Use validators for test/mock data, not production configs.


Don't Mix Validators with Assertions

Validators generate new values each time. They can't be compared.

//  Anti-pattern: This will never match
testId = @uuid
expectedId = @uuid
isMatch = testId == expectedId  // Always false!

//  Better: Assign once, reuse
testId := @uuid
config = { id = testId, reference = testId }

Include Chaos

Don't Create Circular Includes

JSSON doesn't allow circular dependencies, but even indirect ones cause confusion.

//  Anti-pattern: Circular dependency
// a.jsson includes b.jsson
// b.jsson includes c.jsson
// c.jsson includes a.jsson  ← ERROR

Rule: Organize includes in a tree structure, not a graph.


Don't Include Without Purpose

Each include should add meaningful content.

//  Anti-pattern: Include for one value
// database.jsson
dbPort = 5432

// main.jsson
include "database.jsson"
config = { port = dbPort }

//  Better: Inline simple values
config = { port = 5432 }

Rule: Use includes for 10+ lines of config or true modularity.


Boolean Confusion

Don't Mix Boolean Styles Randomly

Pick one style and be consistent.

//  Anti-pattern: Mixed styles
config {
  enabled = true
  active = yes
  running = on
  debug = false
}

//  Better: Consistent style
config {
  enabled = yes
  active = yes
  running = yes
  debug = no
}

Rule: Choose true/false, yes/no, or on/off — and stick with it per project.


Performance

Don't Generate Millions Without Streaming

Large ranges can exhaust memory.

//  Anti-pattern: 1M records without streaming
massiveData = 1..1000000 map (x) = { id = x }

//  Better: Enable streaming
// CLI: jsson -i data.jsson -stream

Rule: For 10,000+ items, use streaming mode (-stream flag).


Summary

Anti-PatternWhy It's BadFix
Logic for static dataUnnecessary complexityUse plain values
4+ nested mapsUnreadableFlatten with templates
Single-use presetsNo reuse benefitInline the values
Validators in prodNon-deterministicUse explicit values
Circular includesBuild errorsTree structure
Mixed boolean stylesInconsistentPick one style
Large ranges without streamMemory explosionUse -stream flag

On this page