PureYAMLJSON is a separate library product layered on the core engine. JSON is a subset of YAML 1.2, so the existing parser already reads both into one value tree; this product adds the missing half and the value-level policy: - JSON.Writer: a pure-Swift RFC-8259 serializer (no Foundation; WASI-clean), pretty or compact, rejecting non-string keys and non-finite numbers. - JSON representability rules expressed in PureYAML's own Validation framework: mappingKeysAreStrings and numbersAreFinite join the core mappingKeysAreUnique. - JSON.Validator: the representability rule set plus issues(for:)/isRepresentable. - JSON.Convert: standalone convert(_:to:) with the round-trip law (parse -> validate representability -> emit -> re-parse must equal the source). To JSON rejects complex keys and non-finite numbers; to YAML rejects duplicate keys, which are legal in JSON but not in YAML. 19 tests cover the writer, the rules, and both conversion directions including the dual-rejection edges. Carved out of the catch-all Sources/Tests paths via exclude so the core PureYAML target is unchanged.
51 lines
1.9 KiB
Swift
51 lines
1.9 KiB
Swift
import PureYAML
|
|
@testable import PureYAMLJSON
|
|
import Testing
|
|
|
|
@Suite("JSON Writer")
|
|
struct JSONWriterTests {
|
|
@Test("Emits a compact object on one line")
|
|
func test_emitsCompactObject() throws {
|
|
let value = try PureYAML.parse("a: 1\nb:\n - true\n - null")
|
|
let json = try PureYAML.JSON.Writer.string(from: value, options: .compact)
|
|
#expect(json == "{\"a\":1,\"b\":[true,null]}")
|
|
}
|
|
|
|
@Test("Pretty output indents and survives a round-trip")
|
|
func test_emitsPrettyObject() throws {
|
|
let value = try PureYAML.parse("a: 1\nb:\n - x")
|
|
let json = try PureYAML.JSON.Writer.string(from: value, options: .pretty)
|
|
#expect(json.contains("\n"))
|
|
#expect(try PureYAML.parse(json) == value)
|
|
}
|
|
|
|
@Test("Empty containers emit as [] and {}")
|
|
func test_emitsEmptyContainers() throws {
|
|
let object = try PureYAML.JSON.Writer.string(from: .mapping(.init([])), options: .compact)
|
|
let array = try PureYAML.JSON.Writer.string(from: .sequence([]), options: .compact)
|
|
#expect(object == "{}")
|
|
#expect(array == "[]")
|
|
}
|
|
|
|
@Test("A non-string mapping key is rejected")
|
|
func test_rejectsNonStringKey() {
|
|
let value = PureYAML.Model.Value.mapping(.init([.init(keyNode: .sequence([.int(1)]), value: .int(2))]))
|
|
#expect(throws: PureYAML.JSON.Writer.Failure.self) {
|
|
_ = try PureYAML.JSON.Writer.string(from: value)
|
|
}
|
|
}
|
|
|
|
@Test("A non-finite number is rejected")
|
|
func test_rejectsNonFiniteNumber() {
|
|
#expect(throws: PureYAML.JSON.Writer.Failure.nonFiniteNumber(.infinity)) {
|
|
_ = try PureYAML.JSON.Writer.string(from: .double(.infinity))
|
|
}
|
|
}
|
|
|
|
@Test("Control characters and quotes are escaped per RFC 8259")
|
|
func test_escapesControlCharacters() throws {
|
|
let json = try PureYAML.JSON.Writer.string(from: .string("a\"b\\c\n\u{01}"), options: .compact)
|
|
#expect(json == "\"a\\\"b\\\\c\\n\\u0001\"")
|
|
}
|
|
}
|