JSON
JSON marshals any Go value to JSON; RawJSON accepts pre-serialized bytes. Both emit the result with syntax highlighting.

// Marshal a Go value
clog.Info().JSON("user", userStruct).Msg("ok")
clog.Info().JSON("config", map[string]any{"port": 8080, "debug": true}).Msg("started")
// Pre-serialized bytes (no marshal overhead)
clog.Error().
Str("batch", "1/1").
RawJSON("error", []byte(`{"status":"unprocessable_entity","detail":"validation failed","code":null}`)).
Msg("Batch failed")
// ERR ❌ Batch failed batch=1/1 error={"status":"unprocessable_entity","detail":"validation failed","code":null}
Use JSON when you have a Go value to log; use RawJSON when you already have bytes (HTTP response bodies, json.RawMessage, database JSON columns) to avoid an unnecessary marshal/unmarshal round-trip. JSON logs the error string as the field value if marshalling fails.
Pretty-printed JSON is automatically flattened to a single line. Highlighting uses a Dracula-inspired colour scheme by default (space after commas included). Disable or customise it via FieldJSON in Styles:
// Disable highlighting
styles := clog.DefaultStyles()
styles.FieldJSON = nil
clog.SetStyles(styles)
// Custom colours
custom := clog.DefaultJSONStyles()
custom.Key = new(lipgloss.NewStyle().Foreground(lipgloss.Color("#50fa7b")))
styles.FieldJSON = custom
clog.SetStyles(styles)
Number is the base fallback for all numeric tokens. Five sub-styles allow finer control and fall back to Number when nil:
| Field | Applies to |
|---|---|
NumberPositive | Positive numbers (with or without explicit +) |
NumberNegative | Negative numbers |
NumberZero | Zero (falls back to NumberPositive, then Number) |
NumberFloat | Floating-point values |
NumberInteger | Integer values |
custom := clog.DefaultJSONStyles()
custom.NumberNegative = new(lipgloss.NewStyle().Foreground(lipgloss.Color("1"))) // red
custom.NumberZero = new(lipgloss.NewStyle().Foreground(lipgloss.Color("8"))) // grey
styles.FieldJSON = custom
clog.SetStyles(styles)
Rendering Modes
Set JSONStyles.Mode to control how JSON structure is rendered:
| Mode | Description | Example |
|---|---|---|
JSONModeJSON | Standard JSON (default) | {"status":"ok","count":42} |
JSONModeHuman | Unquote keys and simple string values | {status:ok, count:42} |
JSONModeFlat | Flatten nested object keys with dot notation; arrays kept intact | {status:ok, meta.region:us-east-1} |
JSONModeHuman - keys are unquoted unless they contain ,{}[]\s:#"' or start with ////*. String values are unquoted unless they start with a forbidden character, end with whitespace, are ambiguous as a JSON keyword (true, false, null), or look like a number. Empty strings always render as "".
styles.FieldJSON = clog.DefaultJSONStyles()
styles.FieldJSON.Mode = clog.JSONModeHuman
clog.Info().
RawJSON("response", []byte(`{"status":"ok","count":42,"active":true,"deleted_at":null}`)).
Msg("Fetched")
// INF ℹ️ Fetched response={status:ok, count:42, active:true, deleted_at:null}
JSONModeFlat - nested objects are recursed into and their keys joined with .; arrays are kept intact as values:
styles.FieldJSON.Mode = clog.JSONModeFlat
clog.Info().
RawJSON("resp", []byte(`{"user":{"name":"alice","role":"admin"},"tags":["a","b"]}`)).
Msg("Auth")
// INF ℹ️ Auth resp={user.name:alice, user.role:admin, tags:[a, b]}
Spacing
JSONStyles.Spacing is a bitmask controlling where spaces are inserted. The default (DefaultJSONStyles) adds a space after commas.
| Flag | Effect | Example |
|---|---|---|
JSONSpacingAfterColon | Space after : | {"key": "value"} |
JSONSpacingAfterComma | Space after , | {"a":1, "b":2} |
JSONSpacingBeforeObject | Space before a nested { | {"key": {"n":1}} |
JSONSpacingBeforeArray | Space before a nested [ | {"tags": ["a","b"]} |
JSONSpacingAll | All of the above | {"key": {"n": 1}, "tags": ["a"]} |
// Fluent builder
styles.FieldJSON = clog.DefaultJSONStyles().WithSpacing(clog.JSONSpacingAll)
// Direct assignment
styles.FieldJSON.Spacing = clog.JSONSpacingAfterComma | clog.JSONSpacingBeforeObject
JSONSpacingAfterColon and JSONSpacingBeforeObject/JSONSpacingBeforeArray are independent - combining them produces two spaces before a nested value.
Omitting Commas
Set OmitCommas: true to drop the , separator. Combine with JSONSpacingAfterComma to keep a space in its place:
styles.FieldJSON.OmitCommas = true
styles.FieldJSON.Spacing |= clog.JSONSpacingAfterComma
clog.Info().
RawJSON("r", []byte(`{"a":1,"b":2,"c":true}`)).
Msg("ok")
// INF ℹ️ ok r={a:1 b:2 c:true}