mapstructure

A Go library for decoding generic map values into strongly typed structs, and back again.

Library
Go
vv1.5.0
8,011 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
41 /100 Fair
Development Activity 0
Maintenance 0
Community 64
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
75 /100 Good
Architecture 75
Code Quality 80
Innovation 78
Learning Curve 65

mapstructure is a lightweight, dependency-free Go library for converting map[string]interface{} values into native Go structs and vice versa. It solves a common problem in Go programs that decode loosely-typed data — JSON, YAML, HCL, command-line flags — where the shape of the data isn’t fully known until runtime.

Beyond basic decoding, mapstructure supports struct tags for field renaming, embedded struct squashing, weakly-typed input coercion, decode hooks for custom type conversions, and metadata tracking for unused keys. It’s a foundational dependency in tools like HashiCorp’s Terraform, Vault, and Packer, where configuration often arrives as untyped maps that need to become strongly typed Go values.

What You Get

  • Bidirectional decode/encode between maps and structs
  • Struct tag support for field renaming and squashing embedded types
  • Configurable decode hooks for custom type conversions
  • Weakly-typed input coercion for loosely-typed sources like CLI flags or PHP-style JSON
  • Metadata tracking of unused/unset keys for stricter validation

Common Use Cases

  • Configuration loading from parsed YAML/JSON/HCL into typed config structs
  • CLI flag binding where values arrive as loosely-typed strings
  • Plugin/RPC boundary decoding of untyped map payloads into internal Go types
  • Dynamic JSON handling when a payload’s shape isn’t known until a discriminator field is read

Under The Hood

Architecture

mapstructure centers on a single exported Decode/NewDecoder entrypoint backed by an internal decoder type that dispatches by reflect.Kind across a flat, single-package codebase (mapstructure.go). Configuration is expressed through a DecoderConfig struct covering tag name, squash behavior, weak typing, and hook registration, while decode_hooks.go isolates the hook composition logic (DecodeHookFuncType/Kind/Value, ComposeDecodeHookFunc) as a separable concern from the core decode loop, and error.go aggregates per-field failures into a single multi-error value. There is no internal package layering — the entire library lives in one flat namespace, keeping the public surface small and predictable, though it means the reflection-heavy decode logic and configuration concerns share the same file.

Tech Stack

The library has zero external dependencies, relying only on the Go standard library (reflect, encoding, errors, fmt, net, strconv, strings, time); go.mod declares go 1.14 as its floor. A GitHub Actions workflow (test.yml) runs go test ./... on push and pull request against a single Go version, providing basic regression coverage without a separate linting or static-analysis step.

Code Quality

Testing is extensive and comprehensive relative to the library’s size: mapstructure_test.go alone carries roughly 2,800 lines across dozens of test functions, supplemented by a dedicated regression suite (mapstructure_bugs_test.go), hook-specific tests (decode_hooks_test.go), runnable Godoc examples (mapstructure_examples_test.go), and benchmark tests. Error handling is explicit and typed via the custom Error type, which implements both the standard error interface and errwrap.Wrapper for compatibility with multi-error tooling. No linter or formatter configuration is present in the repository.

API Design The public API favors progressive disclosure: the zero-config Decode(input, &output) call covers the common case, while NewDecoder(*DecoderConfig) exposes the full surface — tag renaming, squash, weak typing, decode hooks, and metadata — for advanced use. Package-level Godoc comments walk through each configuration option with inline examples, and struct tags follow conventions familiar from encoding/json, lowering the learning curve for anyone who has decoded JSON in Go before.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers