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 ← ERRORRule: 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 -streamRule: For 10,000+ items, use streaming mode (-stream flag).
Summary
| Anti-Pattern | Why It's Bad | Fix |
|---|---|---|
| Logic for static data | Unnecessary complexity | Use plain values |
| 4+ nested maps | Unreadable | Flatten with templates |
| Single-use presets | No reuse benefit | Inline the values |
| Validators in prod | Non-deterministic | Use explicit values |
| Circular includes | Build errors | Tree structure |
| Mixed boolean styles | Inconsistent | Pick one style |
| Large ranges without stream | Memory explosion | Use -stream flag |