yaml

A Go YAML library that marshals and unmarshals through your existing JSON struct tags, instead of a separate YAML tag system.

Library
Go
vv1.0.0
1,063stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
45/100Fair
Development Activity0
Maintenance20
Community72
Maturity60
Momentum28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
61/100Good
Architecture60
Code Quality55
Innovation55
Learning Curve75

ghodss/yaml is a thin wrapper around go-yaml (gopkg.in/yaml.v2) that changes how YAML gets bound to Go structs. Rather than introducing its own struct-tag dialect, it first converts YAML to JSON internally and then delegates to the standard library’s encoding/json for the actual marshal/unmarshal work. That means any struct already tagged with json:"..." works immediately for YAML too, and any type implementing MarshalJSON/UnmarshalJSON gets that behavior for free when read from or written to YAML — no separate yaml:"..." tags or custom YAML marshalers to maintain.

The package exposes a small, JSON-library-shaped API: Marshal, Unmarshal, UnmarshalStrict (which errors on duplicate mapping keys), and the standalone conversion helpers YAMLToJSON/JSONToYAML. A DisallowUnknownFields option (Go 1.10+) plugs into the underlying JSON decoder for strict schema enforcement. It’s a common dependency wherever a project already has JSON-tagged structs and needs YAML support without keeping two tag sets in sync — most notably it was one of the original YAML libraries used across the early Kubernetes ecosystem.

What You Get

  • Marshal/Unmarshal functions with the same signatures and semantics developers already know from encoding/json
  • Automatic reuse of json:"..." struct tags for YAML fields — no second tag dialect to maintain
  • Automatic reuse of custom MarshalJSON/UnmarshalJSON methods when converting to/from YAML
  • UnmarshalStrict for rejecting YAML documents with duplicate mapping keys
  • Standalone YAMLToJSON/JSONToYAML conversion helpers for working with raw bytes outside of struct binding
  • A DisallowUnknownFields JSON decoder option (Go 1.10+) for strict schema validation

Common Use Cases

  • Adding YAML config-file support to a Go service that already has JSON-tagged request/response structs, without writing a second set of tags
  • Reading Kubernetes-style YAML manifests into typed structs that already implement custom JSON marshaling
  • Round-tripping YAML and JSON representations of the same configuration for tooling that needs to emit either format
  • Validating YAML input strictly (UnmarshalStrict, DisallowUnknownFields) to catch typos in config keys or duplicate map keys early

Under The Hood

Architecture The package is a single flat conversion pipeline rather than a layered system: YAML bytes are parsed into a generic interface{} by gopkg.in/yaml.v2, walked and coerced into JSON-compatible values by an internal convertToJSONableObject pass in yaml.go, and then handed to the standard library’s encoding/json for the actual struct binding. fields.go carries an adapted copy of Go’s own encoding/json struct-field-enumeration logic (typeFields, cachedTypeFields, tag parsing) so that json struct tags can be reused for YAML without reimplementing reflection from scratch, and the one version-gated feature (DisallowUnknownFields) is isolated behind a build-tagged file (yaml_go110.go). There is no plugin surface, no custom type system, and nothing would meaningfully change if the core abstraction shifted — it’s intentionally a thin adapter, not a framework.

Tech Stack A single external dependency, gopkg.in/yaml.v2 v2.2.2, pinned in go.mod with no other third-party packages. Everything else rides on the Go standard library (encoding/json, reflect, bytes, strconv). Build and test tooling is just go build/go test; CI is defined via a legacy .travis.yml, consistent with the repo’s inactive maintenance status.

Code Quality Table-driven tests in yaml_test.go and yaml_go110_test.go cover Marshal, Unmarshal, UnmarshalStrict, and the YAMLToJSON/JSONToYAML round trips using Go’s built-in testing package — no mocking framework needed given the pure-function API surface. Errors are wrapped with fmt.Errorf and pass through the underlying go-yaml/json errors rather than being swallowed. Much of fields.go, however, is adapted directly from the Go project’s own encoding/json internals (carrying a separate BSD-style license block), so its correctness rides more on the stdlib’s track record than on this repo’s own test coverage. There’s no linter configuration and no typed error variants; the project has had no commits since 2023.

API Design The public API is deliberately shaped to mirror encoding/json’s own Marshal/Unmarshal signatures, including a functional-options-style JSONOpt parameter mirroring json.Decoder, so a Go developer already familiar with the standard library needs almost no new mental model — the one addition is UnmarshalStrict/DisallowUnknownFields for stricter parsing. The trade-off for that minimalism is a narrow feature surface: there’s no way to give a field a different name in YAML versus JSON, and go-yaml-specific features like anchors/aliases aren’t exposed through configuration.

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

Search