YamlKit is a pure Swift implementation of YAML 1.2.2 for
macOS and iOS. It provides YAMLDecoder and YAMLEncoder, which plug into Swift's
Codable framework just like JSONDecoder and JSONEncoder, as well as lower-level APIs
for working with YAML node trees and event streams.
- Complete YAML 1.2.2 parser that passes all 402 cases of the official YAML test suite
- Emitter producing idiomatic block-style YAML, quoting strings only where necessary
Codablesupport with date, data, and key strategies (including snake case and kebab case)- Core, JSON, and failsafe schemas, plus support for custom schemas
- Anchors and aliases, multi-document streams,
%YAML/%TAGdirectives, optional merge keys - UTF-8, UTF-16, and UTF-32 input with automatic encoding detection
- Protection against malicious input ("billion laughs", excessive nesting)
- No runtime dependencies; Swift 6 language mode with strict concurrency checking
Add YamlKit to the dependencies of your Package.swift:
dependencies: [
.package(url: "https://github.com/objecthub/swift-yamlkit.git", from: "1.0.0")
],
targets: [
.target(name: "MyTarget", dependencies: [
.product(name: "YamlKit", package: "swift-yamlkit")
])
]The examples below give a quick overview. USAGE.md explains the main use cases in more depth: decoding and encoding strategies, error handling, working with node trees, custom schemas, and streaming with events.
import YamlKit
struct Service: Codable {
var image: String
var replicas: Int
var ports: [Int]
var environment: [String: String]
}
let yaml = """
image: nginx:1.27
replicas: 3
ports: [80, 443]
environment:
TZ: Europe/Zurich
"""
let service = try YAMLDecoder().decode(Service.self, from: yaml)Plain scalars are interpreted according to the YAML 1.2 core schema (3 is an integer,
true a boolean, ~ is null, "3" is a string). Errors are reported as DecodingError
values whose context includes the coding path and the line and column of the problem.
let encoder = YAMLEncoder()
encoder.outputFormatting = [.sortedKeys]
print(try encoder.encodeToString(service))environment:
TZ: Europe/Zurich
image: nginx:1.27
ports:
- 80
- 443
replicas: 3let decoder = YAMLDecoder()
// runs-on → runsOn
decoder.keyDecodingStrategy = .convertFromKebabCase
// 2001-12-14t21:59:43.10-05:00
decoder.dateDecodingStrategy = .timestamp
// <<: *defaults
decoder.parseOptions.resolvesMergeKeys = true
let encoder = YAMLEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
encoder.outputFormatting = [.explicitDocumentStart,
.indentlessSequences]
encoder.indentation = 4Streams with multiple documents are supported via decodeAll(_:from:) and
encodeAll(_:).
let root = try YAML.parse("""
name: YamlKit
tags: [swift, yaml]
""")
print(root?["tags"]?[0]?.string ?? "") // swift
let document: YAMLNode = ["name": "YamlKit", "version": 1, "tags": ["swift", "yaml"]]
print(try YAML.serialize(document))var parser = try YAMLParser(string: "[a, b]")
while let event = try parser.next() {
print(event.kind)
}
let text = try YAML.emit(try YAML.parseEvents("{a: 1}"))YamlKit implements the processing model of chapter 3 of the specification as separate layers:
parse compose decode
YAML text ──────────▶ events ──────────▶ nodes ──────────▶ Swift values
◀────────── events ◀────────── nodes ◀────────── Swift values
emit serialize encode
| Directory | Contents |
|---|---|
Sources/YamlKit/Reader |
Encoding detection and line break normalization |
Sources/YamlKit/Scanner |
Tokenizer: indentation, implicit keys, scalars, properties |
Sources/YamlKit/Parser |
YAMLParser and YAMLEvent |
Sources/YamlKit/Node |
YAMLNode and the composer (tag resolution, aliases) |
Sources/YamlKit/Schema |
YAMLSchema with the core, JSON, and failsafe schemas |
Sources/YamlKit/Emitter |
YAMLEmitter and the serializer |
Sources/YamlKit/Codable |
YAMLDecoder and YAMLEncoder |
The DocC documentation contains API reference, a getting started guide, and a description of the architecture. In Xcode, choose Product ▸ Build Documentation.
Without Xcode, use Scripts/build-documentation.sh. It extracts the symbol graph with SwiftPM and
runs the docc tool of the Swift toolchain (found on the PATH, or via xcrun on macOS), so
the package needs no documentation plugin dependency:
# .build/YamlKit.doccarchive
Scripts/build-documentation.sh archive
# live preview at http://localhost:8080/documentation/yamlkit
Scripts/build-documentation.sh previewTo publish the documentation on a static web server such as GitHub Pages, run:
Scripts/build-documentation.sh site swift-yamlkitThe website is written to .build/docs-site. The second argument is the hosting base path,
i.e. the URL path under which the site is served; swift-yamlkit matches
https://<user>.github.io/swift-yamlkit/. Omit it if the site is served from the root of a
domain. Copy the contents of .build/docs-site to the web server (for GitHub Pages, e.g. to the
docs folder of the publishing branch); the documentation is then available at
<base URL>/documentation/yamlkit/.
The script performs these steps, which can also be run by hand:
swift package dump-symbol-graph --minimum-access-level public
# prints "Files written to <directory>"; copy <directory>/YamlKit*.symbols.json
# into a separate directory, e.g. .build/symbol-graphs
docc convert Sources/YamlKit/Documentation.docc \
--fallback-display-name YamlKit --fallback-bundle-identifier org.objecthub.YamlKit \
--additional-symbol-graph-dir .build/symbol-graphs \
--transform-for-static-hosting --hosting-base-path swift-yamlkit \
--output-path .build/docs-siteOn macOS, use xcrun docc if docc is not on the PATH.
YamlKit is a plain Swift package; there is no separate Xcode project. Open the package directly in Xcode:
xed . # or: open Package.swift, or File ▸ Open… and select the package folderSelect the shared swift-yamlkit scheme (it is versioned in
.swiftpm/xcode/xcshareddata/xcschemes) and a destination such as My Mac or an iOS
Simulator. Then use Product ▸ Build (⌘B), Product ▸ Test (⌘U), the Test navigator to run
individual tests or test-suite cases, and Product ▸ Build Documentation (⌃⇧⌘D). Code coverage
for the YamlKit target is enabled in the scheme and shown in the Report navigator.
Changes to targets, platforms, or resources are made in Package.swift; Xcode picks them up
automatically. The same scheme works from the command line:
xcodebuild test -scheme swift-yamlkit -destination 'platform=macOS'
xcodebuild test -scheme swift-yamlkit -destination 'platform=iOS Simulator,name=<simulator name>'xcodebuild -scheme swift-yamlkit -showdestinations lists the available simulators.
swift testThe test suite includes unit tests for every layer, randomized round-trip tests, and
conformance tests based on a vendored snapshot of the YAML test suite. For every case of
the suite, the tests verify the parsing events, the composed data (against in.json),
and that emitting and serializing preserve the content. The snapshot can be updated with
Scripts/update-yaml-test-suite.sh.
The tests use DynamicJSON to read the expected JSON data. It is a test-only dependency: packages that depend on YamlKit neither fetch nor link it.
The following technologies are needed to build the YamlKit framework. The framework can both be built either using Xcode or the Swift Package Manager.
- Swift 6
- Swift Package Manager
- macOS 13 or later, iOS 16 or later
YamlKit is distributed under the Apache License, Version 2.0. See LICENSE. The YAML test suite data is distributed under the MIT license by its authors.
Author: Matthias Zenger (matthias@objecthub.com)
Copyright © 2026 Matthias Zenger. All rights reserved.