Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

README.md

JSON Schema defaults and variable substitution

Synthra automatically applies "default" values declared in a JSON Schema to any missing keys after loading sources. This includes defaults nested inside "properties" and "patternProperties". Combined with WithEnvSubst, you can expand ${VAR} placeholders in string values before validation runs.

What it shows

  • WithJSONSchema(schema) filling in missing top-level and nested keys from "default" declarations.
  • patternProperties defaults applied to every existing matching key (the components map).
  • WithEnvSubst expanding ${ENV} placeholders in string values after schema defaults are applied.
  • User-provided values are never overridden by schema defaults.

The config

config.yaml is intentionally minimal. Only required and non-default values are specified:

service: my-app
server:
  max_connections: 50
components:
  web:
    image: nginx:1.27
  worker:
    image: my-app:latest
    role: worker
    replicas: 3

The schema (key excerpts)

{
  "required": ["service"],
  "properties": {
    "port":      { "default": 8080 },
    "log_level": { "default": "info" },
    "server": {
      "properties": {
        "timeout":         { "default": "30s" },
        "max_connections": { "default": 100 }
      }
    },
    "components": {
      "patternProperties": {
        "^[a-z0-9-]+$": {
          "properties": {
            "role":     { "default": "service" },
            "replicas": { "default": 1 }
          }
        }
      }
    }
  }
}

After loading

Key Source
service config.yaml
port schema default (8080)
log_level schema default (info)
server.timeout schema default (30s)
server.max_connections config.yaml (50)
components.web.role schema patternProperties default (service)
components.web.replicas schema patternProperties default (1)
components.worker.role config.yaml (worker)
components.worker.replicas config.yaml (3)

Variable substitution with WithEnvSubst

The program sets ENV=production and passes it through resolve.Vars. If a config field contains ${ENV}, it is expanded to production after schema defaults are applied.

For example, if you add envfile: ".env.${ENV}" to config.yaml, it becomes .env.production after Load.

Use ${VAR:-fallback} to provide a default for variables that may not be set.

Compose multiple resolver sources with .Or. The first resolver that finds a variable wins (highest priority first):

synthra.WithEnvSubst(
    synthra.FromEnv().Prefix("APP_").          // highest: prefixed OS env
        Or(synthra.FromMap(map[string]string{  // lowest:  static defaults
            "ENV": env,
        })),
)

Run

cd examples/schema && go run .

Tests

cd examples/schema && go test -v