Skip to content

Commit c316760

Browse files
authored
Add Codable conformance (#4)
1 parent daf272a commit c316760

File tree

6 files changed

+95
-15
lines changed

6 files changed

+95
-15
lines changed

.github/workflows/ci.yml

+5-7
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,12 @@ name: CI
33
on: push
44

55
jobs:
6-
library:
7-
runs-on: macos-12
6+
test:
7+
runs-on: macos-13
88

99
steps:
1010
- uses: actions/checkout@v3
11-
- name: Select Xcode 14
12-
run: sudo xcode-select -s /Applications/Xcode_14.1.app
13-
- name: Build
14-
run: swift build -v
11+
- name: Select Xcode 15
12+
run: sudo xcode-select -s /Applications/Xcode_15.0.app
1513
- name: Test
16-
run: swift test -v
14+
run: swift test

.swift-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
5.7.0
1+
5.9.0
22

Package.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// swift-tools-version: 5.7
1+
// swift-tools-version: 5.9
22

33
import PackageDescription
44

Sources/JSON/JSON.swift

+49
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,55 @@ extension JSON: Equatable {
299299
}
300300
}
301301

302+
extension JSON: Codable {
303+
public init(from decoder: Decoder) throws {
304+
let container = try decoder.singleValueContainer()
305+
306+
if container.decodeNil() {
307+
self = .null
308+
} else if let bool = try? container.decode(Bool.self) {
309+
self = .boolean(bool)
310+
} else if let double = try? container.decode(Double.self) {
311+
self = .number(double)
312+
} else if let string = try? container.decode(String.self) {
313+
self = .string(string)
314+
} else if let array = try? container.decode([JSON].self) {
315+
self = .array(array)
316+
} else if let dictionary = try? container.decode([String: JSON].self) {
317+
self = .dictionary(dictionary)
318+
} else {
319+
throw DecodingError.dataCorruptedError(
320+
in: container,
321+
debugDescription: "Invalid JSON value."
322+
)
323+
}
324+
}
325+
326+
public func encode(to encoder: Encoder) throws {
327+
var container = encoder.singleValueContainer()
328+
329+
switch self {
330+
case .null:
331+
try container.encodeNil()
332+
333+
case let .boolean(bool):
334+
try container.encode(bool)
335+
336+
case let .number(double):
337+
try container.encode(double)
338+
339+
case let .string(string):
340+
try container.encode(string)
341+
342+
case let .array(array):
343+
try container.encode(array)
344+
345+
case let .dictionary(dictionary):
346+
try container.encode(dictionary)
347+
}
348+
}
349+
}
350+
302351
public extension JSON? {
303352
subscript(key: String) -> JSON? {
304353
get {

Tests/JSONTests/JSONTests.swift

+25
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,31 @@ final class JSONTests: XCTestCase {
259259
XCTAssertTrue(JSON.string("boom") as JSON? == "boom")
260260
}
261261

262+
func testCodable() throws {
263+
let json: JSON = [
264+
"one": 2,
265+
"two_text": "two",
266+
"pi": 3.14,
267+
"yes": true,
268+
"null": nil,
269+
"object": [
270+
"three": 3,
271+
"four_text": "four",
272+
"null": nil,
273+
"inner_array": [
274+
"index_0",
275+
false,
276+
4.20,
277+
] as [Any?],
278+
] as [String: Any?],
279+
]
280+
281+
let encoded = try JSONEncoder().encode(json)
282+
let decoded = try JSONDecoder().decode(JSON.self, from: encoded)
283+
284+
XCTAssertEqual(decoded, json)
285+
}
286+
262287
func testInitWithLiteralTypes() throws {
263288
XCTAssertEqual(
264289
JSON.array([.boolean(true), .number(3.14), .null]),

bin/format.sh

+14-6
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,25 @@
11
#!/usr/bin/env bash
2+
# https://sharats.me/posts/shell-script-best-practices/
23

3-
set -e
4+
set -o errexit
5+
set -o nounset
6+
set -o pipefail
7+
if [[ "${TRACE-0}" == "1" ]]; then
8+
set -o xtrace
9+
fi
410

5-
SELF=`realpath $0`
6-
DIR=`dirname $SELF`
7-
DEV_DIR=`echo ${DIR%/*}`
11+
if [[ "${1-}" =~ ^-*h(elp)?$ ]]; then
12+
echo 'Usage: ./format.sh'
13+
exit
14+
fi
815

9-
pushd "$DEV_DIR" &>/dev/null
16+
DIR=`dirname "$0"`
17+
pushd "$DIR/.." &>/dev/null
1018

1119
if command -v swiftformat >/dev/null 2>&1; then
1220
swiftformat --quiet --config .swiftformat .
1321
else
14-
echo "warning: Install swiftformat by running 'brew install swiftformat'"
22+
echo "warning: Install swiftformat by running 'brew install swiftformat'" >&2
1523
fi
1624

1725
popd &>/dev/null

0 commit comments

Comments
 (0)