Go to file
JP Simard a34f950531
Handle empty dictionaries (#394)
2023-06-03 08:26:07 -04:00
.bcr Update BCR presubmit to only build, not test (#382) 2023-01-17 09:30:21 -05:00
.github/workflows [CI] Run some jobs with Swift 5.8 / Xcode 14.3 (#392) 2023-04-24 14:38:16 -04:00
Sources Handle empty dictionaries (#394) 2023-06-03 08:26:07 -04:00
Tests Handle empty dictionaries (#394) 2023-06-03 08:26:07 -04:00
Yams.xcodeproj Release 5.0.5 2023-02-20 11:24:22 -05:00
cmake/modules build: add ARM64 architecture mapping for Windows (#390) 2023-03-12 11:03:21 -04:00
.bazelrc Migrate to bzlmod (#377) 2023-01-13 16:31:34 -05:00
.bazelversion Set `.bazelversion` to 6.0.0 & update rules_apple to 2.0.0 (#360) 2023-01-06 10:13:07 -05:00
.codecov.yml Run CI jobs with Swift 5.2 (#246) 2020-04-16 15:45:23 -07:00
.gitignore Add bazel support to Yams (#302) 2021-03-22 10:27:51 -07:00
.jazzy.yaml Rename master branch to main 2020-12-11 14:21:03 -05:00
.spi.yml Add DocC plugin and integrate with Swift Package Index (#354) 2022-06-05 13:28:58 -04:00
.swiftlint.yml [CI] Run some jobs with Swift 5.8 / Xcode 14.3 (#392) 2023-04-24 14:38:16 -04:00
BUILD Use common rules_swift name (#389) 2023-02-17 17:26:50 -05:00
CHANGELOG.md Handle empty dictionaries (#394) 2023-06-03 08:26:07 -04:00
CMakeLists.txt build: add the ability to run the test suite from CMake (#256) 2020-05-15 16:39:33 -07:00
CONTRIBUTING.md [Docs] Add "Updating CI Jobs" section to CONTRIBUTING.md (#284) 2020-11-03 13:49:49 -08:00
Docs.md update "Customize Parsing" examples (#294) 2020-12-31 12:12:58 -08:00
Gemfile Add jazzy to Gemfile 2018-05-06 11:26:49 -07:00
Gemfile.lock Bump activesupport from 6.1.7.1 to 6.1.7.3 (#391) 2023-03-17 08:22:42 -04:00
LICENSE first commit 2016-11-19 13:59:58 -08:00
MODULE.bazel Release 5.0.5 2023-02-20 11:24:22 -05:00
Package.swift Remove conditional docc-plugin dependency (#388) 2023-02-03 10:42:51 -05:00
README.md Release 5.0.5 2023-02-20 11:24:22 -05:00
WORKSPACE Migrate to bzlmod (#377) 2023-01-13 16:31:34 -05:00
Yams.podspec Release 5.0.5 2023-02-20 11:24:22 -05:00
yams.jpg add image to readme 2016-11-20 11:26:22 -08:00

README.md

Yams

Yams

A sweet and swifty YAML parser built on LibYAML.

SwiftPM xcodebuild pod lib lint Nightly codecov

Installation

Building Yams requires Xcode 12.5+ or a Swift 5.4+ toolchain with the Swift Package Manager or CMake and Ninja.

CMake

CMake 3.17.2 or newer is required, along with Ninja 1.9.0 or newer.

When building for non-Apple platforms:

cmake -B /path/to/build -G Ninja -S /path/to/yams -DCMAKE_BUILD_TYPE=Release -DFoundation_DIR=/path/to/foundation/build/cmake/modules
cmake --build /path/to/build

To build for Apple platforms (macOS, iOS, tvOS, watchOS), there is no need to spearately build Foundation because it is included as part of the SDK:

cmake -B /path/to/build -G Ninja -S /path/to/yams -DCMAKE_BUILD_TYPE=Release
cmake --build /path/to/build

Swift Package Manager

Add .package(url: "https://github.com/jpsim/Yams.git", from: "5.0.5") to your Package.swift file's dependencies.

CocoaPods

Add pod 'Yams' to your Podfile.

Carthage

Add github "jpsim/Yams" to your Cartfile.

Bazel

In your WORKSPACE file

YAMS_GIT_SHA = "SOME_SHA"
http_archive(
    name = "com_github_jpsim_yams",
    urls = [
        "https://github.com/jpsim/Yams/archive/%s.zip" % YAMS_GIT_SHA,
    ],
    strip_prefix = "Yams-%s" % YAMS_GIT_SHA,
)

Usage

Yams has three groups of conversion APIs: one for use with Codable types, another for Swift Standard Library types, and a third one for a Yams-native representation.

Codable types

  • Codable is an encoding & decoding strategy introduced in Swift 4 enabling easy conversion between YAML and other Encoders like JSONEncoder and PropertyListEncoder.
  • Lowest computational overhead, equivalent to Yams.Node.
  • Encoding: YAMLEncoder.encode(_:) Produces a YAML String from an instance of type conforming to Encodable.
  • Decoding: YAMLDecoder.decode(_:from:) Decodes an instance of type conforming to Decodable from YAML String or Data.
import Foundation
import Yams

struct S: Codable {
    var p: String
}

let s = S(p: "test")
let encoder = YAMLEncoder()
let encodedYAML = try encoder.encode(s)
encodedYAML == """
p: test

"""
let decoder = YAMLDecoder()
let decoded = try decoder.decode(S.self, from: encodedYAML)
s.p == decoded.p

Swift Standard Library types

  • The type of Swift Standard Library is inferred from the contents of the internal Yams.Node representation by matching regular expressions.
  • This method has the largest computational overhead When decoding YAML, because the type inference of all objects is done up-front.
  • It may be easier to use in such a way as to handle objects created from JSONSerialization or if the input is already standard library types (Any, Dictionary, Array, etc.).
  • Encoding: Yams.dump(object:) Produces a YAML String from an instance of Swift Standard Library types.
  • Decoding: Yams.load(yaml:) Produces an instance of Swift Standard Library types as Any from YAML String.
// [String: Any]
let dictionary: [String: Any] = ["key": "value"]
let mapYAML: String = try Yams.dump(object: dictionary)
mapYAML == """
key: value

"""
let loadedDictionary = try Yams.load(yaml: mapYAML) as? [String: Any]

// [Any]
let array: [Int] = [1, 2, 3]
let sequenceYAML: String = try Yams.dump(object: array)
sequenceYAML == """
- 1
- 2
- 3

"""
let loadedArray: [Int]? = try Yams.load(yaml: sequenceYAML) as? [Int]

// Any
let string = "string"
let scalarYAML: String = try Yams.dump(object: string)
scalarYAML == """
string

"""
let loadedString: String? = try Yams.load(yaml: scalarYAML) as? String

Yams.Node

  • Yams' native model representing Nodes of YAML which provides all functions such as detection and customization of the YAML format.
  • Depending on how it is used, computational overhead can be minimized.
  • Encoding: Yams.serialize(node:) Produces a YAML String from an instance of Node.
  • Decoding Yams.compose(yaml:) Produces an instance of Node from YAML String.
var map: Yams.Node = [
    "array": [
        1, 2, 3
    ]
]
map.mapping?.style = .flow
map["array"]?.sequence?.style = .flow
let yaml = try Yams.serialize(node: map)
yaml == """
{array: [1, 2, 3]}

"""
let node = try Yams.compose(yaml: yaml)
map == node

Integrating with Combine

When Apple's Combine framework is available, YAMLDecoder conforms to the TopLevelDecoder protocol, which allows it to be used with the decode(type:decoder:) operator:

import Combine
import Foundation
import Yams

func fetchBook(from url: URL) -> AnyPublisher<Book, Error> {
    URLSession.shared.dataTaskPublisher(for: url)
        .map(\.data)
        .decode(type: Book.self, decoder: YAMLDecoder())
        .eraseToAnyPublisher()
}

License

Both Yams and libYAML are MIT licensed.