From bda835f4b816730f2b645a74f2513a8422609c66 Mon Sep 17 00:00:00 2001 From: Joannis Orlandos Date: Mon, 23 Oct 2017 10:13:10 +0200 Subject: [PATCH] encoding arrays in cheetah --- Sources/Cheetah/Codable.swift | 20 +++++++-- Tests/CheetahTests/ParserTests.swift | 62 ++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 4 deletions(-) diff --git a/Sources/Cheetah/Codable.swift b/Sources/Cheetah/Codable.swift index 25e1f57..b8fecd6 100644 --- a/Sources/Cheetah/Codable.swift +++ b/Sources/Cheetah/Codable.swift @@ -21,6 +21,13 @@ public class JSONEncoder { return encoder.target.object } + public func encodeArray(_ value: Encodable) throws -> JSONArray { + let encoder = _JSONEncoder(target: .array(JSONArray())) + try value.encode(to: encoder) + + return encoder.target.array + } + public func encode(value: Encodable) throws -> Value? { let encoder = _JSONEncoder(target: .primitive(get: { nil }, set: { _ in })) try value.encode(to: encoder) @@ -154,7 +161,7 @@ fileprivate class _JSONEncoder : Encoder, _JSONCodingPathContaining { extension JSONArray { fileprivate subscript(index: Int) -> Value? { get { - if self.count > index { + guard self.count > index else { return nil } @@ -198,12 +205,17 @@ fileprivate struct _JSONUnkeyedEncodingContainer : UnkeyedEncodingContainer { } private func nestedEncoder() -> _JSONEncoder { + let index = self.encoder.target.array.count + return _JSONEncoder(codingPath: codingPath, target: .primitive(get: { - let index = self.encoder.target.array.count return self.encoder.target.array[index] }, set: { value in if let value = value { - self.encoder.target.array.append(value) + if self.encoder.target.array.count > index { + self.encoder.target.array[index] = value + } else { + self.encoder.target.array.append(value) + } } })) } @@ -774,7 +786,7 @@ fileprivate class _JSONUnkeyedDecodingContainer : UnkeyedDecodingContainer, _JSO self.codingPath = decoder.codingPath } - var count: Int? { return decoder.target.object.count } + var count: Int? { return decoder.target.array.count } var currentIndex: Int = 0 var isAtEnd: Bool { return currentIndex >= self.count! diff --git a/Tests/CheetahTests/ParserTests.swift b/Tests/CheetahTests/ParserTests.swift index b227034..00607c0 100644 --- a/Tests/CheetahTests/ParserTests.swift +++ b/Tests/CheetahTests/ParserTests.swift @@ -17,6 +17,12 @@ struct BrokenArray: Codable { ] } +struct User: Codable { + var id: Int + var username: String + var other: Bool +} + class ParsingTests: XCTestCase { func testBrokenJSONArray() throws { @@ -32,6 +38,62 @@ class ParsingTests: XCTestCase { XCTAssertEqual(array.count, 3) } + func testCodable() throws { + let user0 = User(id: 0, username: "test0", other: true) + let user1 = User(id: 1, username: "test1", other: false) + let user2 = User(id: 2, username: "test2", other: false) + let user3 = User(id: 3, username: "test3", other: true) + + var obj0 = try JSONEncoder().encode(user0) + var obj1 = try JSONEncoder().encode(user1) + var obj2 = try JSONEncoder().encode(user2) + var obj3 = try JSONEncoder().encode(user3) + + XCTAssertEqual(Int(obj0["id"]), 0) + XCTAssertEqual(Int(obj1["id"]), 1) + XCTAssertEqual(Int(obj2["id"]), 2) + XCTAssertEqual(Int(obj3["id"]), 3) + + XCTAssertEqual(String(obj0["username"]), "test0") + XCTAssertEqual(String(obj1["username"]), "test1") + XCTAssertEqual(String(obj2["username"]), "test2") + XCTAssertEqual(String(obj3["username"]), "test3") + + XCTAssertEqual(Bool(obj0["other"]), true) + XCTAssertEqual(Bool(obj1["other"]), false) + XCTAssertEqual(Bool(obj2["other"]), false) + XCTAssertEqual(Bool(obj3["other"]), true) + + let value = try JSONEncoder().encodeArray([user0, user1, user2, user3]) + + guard let array0 = JSONArray(value) else { + XCTFail() + return + } + + XCTAssertEqual(array0.count, 4) + + obj0 = JSONObject(array0[0])! + obj1 = JSONObject(array0[1])! + obj2 = JSONObject(array0[2])! + obj3 = JSONObject(array0[3])! + + XCTAssertEqual(Int(obj0["id"]), 0) + XCTAssertEqual(Int(obj1["id"]), 1) + XCTAssertEqual(Int(obj2["id"]), 2) + XCTAssertEqual(Int(obj3["id"]), 3) + + XCTAssertEqual(String(obj0["username"]), "test0") + XCTAssertEqual(String(obj1["username"]), "test1") + XCTAssertEqual(String(obj2["username"]), "test2") + XCTAssertEqual(String(obj3["username"]), "test3") + + XCTAssertEqual(Bool(obj0["other"]), true) + XCTAssertEqual(Bool(obj1["other"]), false) + XCTAssertEqual(Bool(obj2["other"]), false) + XCTAssertEqual(Bool(obj3["other"]), true) + } + func testEncodeArrayJSON() throws { let tests: [Test] = [ 0, 1, 2, 3, 4, 5