New Text Encoder with Flattened Dot-Separated Keys for Improved Readability and Performance
Is your feature request related to a problem? Please describe.
Zap’s current encoders (JSON, console) don’t provide an easy-to-read text output for nested objects:
- JSONEncoder is structured but verbose and less operator-friendly for quick inspection in terminals.
- ConsoleEncoder is compact but does not handle nested objects in a way that makes them easy to grep or read.
- Alternatives like Kubernetes’ klog textlogger and Go’s slog.TextHandler provide text output, but are either slower or less flexible.
Describe the solution you'd like
Introduce a new zapcore.Encoder implementation (e.g., TextEncoder) with the following features:
Dot-flattened keys for nested objects
Example:logger.Info("user created", zap.Any("user", User{ Name: "Alice", Addr: Addr{City: "Bangalore", Zip: "560001"}, }))Current JSONEncoder output:
{"user": {"Name": "Alice", "Addr": {"City": "Bangalore", "Zip": "560001"}}}Proposed TextEncoder output:
"user.Name"="Alice" "user.Addr.City"="Bangalore" "user.Addr.Zip"="560001"This makes logs more human-readable and grep-friendly.
Performance improvements
Benchmarks show this encoder is faster than both k8s textlogger and slog.TextHandler, while competitive with zap’s json encoder.Seamless zap integration
- Provided as a
zapcore.Encoderimplementation. - Configurable via
zapcore.NewTextEncoder(cfg)or zap configuration.
- Provided as a
Describe alternatives you've considered
- Using JSONEncoder → too verbose and not grep-friendly.
- Using ConsoleEncoder → compact but nested structures are still hard to scan.
- Using Kubernetes’ klog textlogger / slog.TextHandler → slower and not integrated with zap.
Is this a breaking change?
No. This would be an additive change introducing a new encoder.
Existing users of JSONEncoder and ConsoleEncoder remain unaffected.
Additional context
- Prototype implementation: github.com/sagarsuperuser/zap/tree/text-encoder
- Includes tests, benchmarks (https://github.com/sagarsuperuser/zap/tree/text-encoder/benchmarks)
- Benchmarks :
Log a message and 10 fields
(https://github.com/sagarsuperuser/zap/tree/text-encoder#log-a-message-and-10-fields)
| Package | Time (ns/op) | Time % vs Zap | Objects Allocated |
|---|---|---|---|
| ⚡ zap (json) | 656 | +0% | 5 allocs/op |
| ⚡ zap (text) | 852 | +30% | 5 allocs/op |
| ⚡ zap (sugared json) | 854 | +30% | 10 allocs/op |
| ⚡ zap (sugared text) | 1071 | +63% | 10 allocs/op |
| zerolog | 318 | -52% | 1 alloc/op |
| go-kit | 1989 | +203% | 56 allocs/op |
| slog | 2122 | +224% | 41 allocs/op |
| slog (LogAttrs) | 2161 | +229% | 40 allocs/op |
| apex/log | 10762 | +1539% | 64 allocs/op |
| log15 | 12049 | +1736% | 73 allocs/op |
| logrus | 12721 | +1840% | 84 allocs/op |
| klog/v2 textlogger | 2776 | +323% | 45 allocs/op |
Example log with nested fields:
"level"="info" "ts"=1758088355.259905 "caller"="zap_test/main.go:57" "msg"="served" "http.request.method"="GET" "http.request.url"="/api/v1/users" "http.response.status"=200 "http.response.bytes"=1234Next Steps
Would the maintainers be open to including this encoder in zap core as an additional zapcore.Encoder implementation? I can submit a draft PR with tests, benchmarks, and documentation once there’s guidance.
Source: uber-go/zap