Skip to content

Commit 8ea29f9

Browse files
authored
Allow JSON extension points. (#46)
1 parent 321e0c5 commit 8ea29f9

File tree

4 files changed

+35
-36
lines changed

4 files changed

+35
-36
lines changed

.github/workflows/ci.yaml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,6 @@ jobs:
9999
run: sudo xcode-select -s /Applications/Xcode_11.4.app/Contents/Developer
100100
- name: Swift version
101101
run: swift --version
102-
# - name: SPM Build
103-
# run: swift build
104-
# - name: SPM Tests
105-
# run: swift test --parallel -Xswiftc -DDEBUG
106102
- name: Xcode Tests
107103
run: |
108104
swift package generate-xcodeproj --skip-extra-files --enable-code-coverage

Sources/PureSwiftJSON/Decoding/JSONDecoder.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,16 @@ public struct JSONDecoder {
88
throws -> T where Bytes.Element == UInt8 {
99
do {
1010
let json = try JSONParser().parse(bytes: bytes)
11-
let decoder = JSONDecoderImpl(userInfo: userInfo, from: json, codingPath: [])
12-
return try decoder.decode(T.self)
11+
return try decode(T.self, from: json)
1312
} catch let error as JSONError {
1413
throw error.decodingError
1514
}
1615
}
16+
17+
@inlinable public func decode<T: Decodable>(_: T.Type, from json: JSONValue) throws -> T {
18+
let decoder = JSONDecoderImpl(userInfo: userInfo, from: json, codingPath: [])
19+
return try decoder.decode(T.self)
20+
}
1721
}
1822

1923
@usableFromInline struct JSONDecoderImpl {

Sources/PureSwiftJSON/Encoding/JSONEncoder.swift

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -101,21 +101,23 @@ public class JSONEncoder {
101101
public init() {}
102102

103103
public func encode<T: Encodable>(_ value: T) throws -> [UInt8] {
104+
let value: JSONValue = try encodeAsJSONValue(value)
105+
var bytes = [UInt8]()
106+
value.appendBytes(to: &bytes)
107+
return bytes
108+
}
109+
110+
public func encodeAsJSONValue<T: Encodable>(_ value: T) throws -> JSONValue {
104111
let encoder = JSONEncoderImpl(userInfo: userInfo, codingPath: [])
105112

106113
try value.encode(to: encoder)
107114

108115
// if the top level encoder does not have a value
109116
// we don't have a value at all and we should return `null`
110-
let value = encoder.value ?? .null
111-
112-
var bytes = [UInt8]()
113-
value.appendBytes(to: &bytes)
114-
return bytes
117+
return encoder.value ?? .null
115118
}
116119
}
117120

118-
/// TBD: This could be done with a struct on the stack, by using inout references.
119121
class JSONEncoderImpl {
120122
let userInfo: [CodingUserInfoKey: Any]
121123
let codingPath: [CodingKey]

Tests/PureSwiftJSONTests/Decoding/JSONDecoderTests.swift

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,15 @@ class JSONDecoderTests: XCTestCase {
5252
}
5353
}
5454

55-
do {
56-
let json = #"{"hello":"world"}"#
57-
let result = try PureSwiftJSON.JSONDecoder().decode(HelloWorld.self, from: json.data(using: .utf8)!)
58-
XCTFail("Did not expect to get a result: \(result)")
59-
} catch let Swift.DecodingError.typeMismatch(type, context) {
60-
// expected
55+
let json = #"{"hello":"world"}"#
56+
XCTAssertThrowsError(_ = try PureSwiftJSON.JSONDecoder().decode(HelloWorld.self, from: json.data(using: .utf8)!)) {
57+
error in
58+
guard case let Swift.DecodingError.typeMismatch(type, context) = error else {
59+
XCTFail("Unexpected error: \(error)"); return
60+
}
61+
6162
XCTAssertTrue(type == [JSONValue].self)
6263
XCTAssertEqual(context.debugDescription, "Expected to decode Array<JSONValue> but found a dictionary instead.")
63-
} catch {
64-
XCTFail("Unexpected error: \(error)")
6564
}
6665
}
6766

@@ -77,16 +76,15 @@ class JSONDecoderTests: XCTestCase {
7776
}
7877
}
7978

80-
do {
81-
let json = #"["haha", "hihi"]"#
82-
let result = try PureSwiftJSON.JSONDecoder().decode(HelloWorld.self, from: json.data(using: .utf8)!)
83-
XCTFail("Did not expect to get a result: \(result)")
84-
} catch let Swift.DecodingError.typeMismatch(type, context) {
85-
// expected
79+
let json = #"["haha", "hihi"]"#
80+
XCTAssertThrowsError(_ = try PureSwiftJSON.JSONDecoder().decode(HelloWorld.self, from: json.data(using: .utf8)!)) {
81+
error in
82+
guard case let Swift.DecodingError.typeMismatch(type, context) = error else {
83+
XCTFail("Unexpected error: \(error)"); return
84+
}
85+
8686
XCTAssertTrue(type == [String: JSONValue].self)
8787
XCTAssertEqual(context.debugDescription, "Expected to decode Dictionary<String, JSONValue> but found an array instead.")
88-
} catch {
89-
XCTFail("Unexpected error: \(error)")
9088
}
9189
}
9290

@@ -101,17 +99,16 @@ class JSONDecoderTests: XCTestCase {
10199
}
102100
}
103101

104-
do {
105-
let json = #"{"hello👩‍👩‍👧‍👧" 123 }"#
106-
let result = try PureSwiftJSON.JSONDecoder().decode(HelloWorld.self, from: json.data(using: .utf8)!)
107-
XCTFail("Did not expect to get a result: \(result)")
108-
} catch let Swift.DecodingError.dataCorrupted(context) {
109-
// expected
102+
let json = #"{"hello👩‍👩‍👧‍👧" 123 }"#
103+
XCTAssertThrowsError(_ = try PureSwiftJSON.JSONDecoder().decode(HelloWorld.self, from: json.data(using: .utf8)!)) {
104+
error in
105+
guard case let Swift.DecodingError.dataCorrupted(context) = error else {
106+
XCTFail("Unexpected error: \(error)"); return
107+
}
108+
110109
XCTAssertEqual(context.codingPath.count, 0)
111110
XCTAssertEqual(context.debugDescription, "Unexpected character `1` at character index: 34")
112111
XCTAssertNotNil(context.underlyingError)
113-
} catch {
114-
XCTFail("Unexpected error: \(error)")
115112
}
116113
}
117114
}

0 commit comments

Comments
 (0)