diff --git a/LeStorage/Services.swift b/LeStorage/Services.swift index 6dc6780..1e69205 100644 --- a/LeStorage/Services.swift +++ b/LeStorage/Services.swift @@ -65,17 +65,16 @@ public class Services { fileprivate var jsonEncoder: JSONEncoder = { let encoder = JSONEncoder() - let dateFormatter = DateFormatter() - dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS" - encoder.dateEncodingStrategy = .formatted(dateFormatter) + encoder.keyEncodingStrategy = .convertToSnakeCase + encoder.outputFormatting = .prettyPrinted + encoder.dateEncodingStrategy = .iso8601 return encoder }() fileprivate var jsonDecoder: JSONDecoder = { let decoder = JSONDecoder() - let dateFormatter = DateFormatter() - dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS" - decoder.dateDecodingStrategy = .formatted(dateFormatter) + decoder.keyDecodingStrategy = .convertFromSnakeCase + decoder.dateDecodingStrategy = .iso8601 return decoder }() @@ -165,6 +164,7 @@ public class Services { do { let token = try self.keychainStore.getToken() + Logger.log("current token = \(token)") request.setValue("Token \(token)", forHTTPHeaderField: "Authorization") } catch { Logger.log("missing token") diff --git a/LeStorage/StoredCollection.swift b/LeStorage/StoredCollection.swift index 4ad0c41..a16c971 100644 --- a/LeStorage/StoredCollection.swift +++ b/LeStorage/StoredCollection.swift @@ -282,7 +282,10 @@ public class StoredCollection: RandomAccessCollection, SomeCollecti throw StoreError.missingService } let jsonString = try instance.jsonString() - let url = baseURL + T.resourceName() + "/" + var url = baseURL + T.resourceName() + "/" + if method == .put || method == .delete { + url += (instance.stringId + "/") + } return ApiCall(url: url, method: method.rawValue, dataId: String(instance.id), body: jsonString) } diff --git a/LeStorage/Utils/Codable+Extensions.swift b/LeStorage/Utils/Codable+Extensions.swift index 1c8e98f..ddaacb4 100644 --- a/LeStorage/Utils/Codable+Extensions.swift +++ b/LeStorage/Utils/Codable+Extensions.swift @@ -7,6 +7,21 @@ import Foundation +fileprivate var jsonEncoder: JSONEncoder = { + let encoder = JSONEncoder() + encoder.keyEncodingStrategy = .convertToSnakeCase + encoder.outputFormatting = .prettyPrinted + encoder.dateEncodingStrategy = .iso8601 + return encoder +}() + +fileprivate var jsonDecoder: JSONDecoder = { + let decoder = JSONDecoder() + decoder.keyDecodingStrategy = .convertFromSnakeCase + decoder.dateDecodingStrategy = .iso8601 + return decoder +}() + extension Encodable { func jsonString() throws -> String { @@ -15,14 +30,11 @@ extension Encodable { } func jsonData() throws -> Data { - let encoder: JSONEncoder = JSONEncoder() - return try encoder.encode(self) + return try jsonEncoder.encode(self) } func prettyJSONString() throws -> String { - let encoder: JSONEncoder = JSONEncoder() - encoder.outputFormatting = .prettyPrinted - let data = try encoder.encode(self) + let data = try jsonEncoder.encode(self) return String(data: data, encoding: .utf8) ?? "" } @@ -43,11 +55,11 @@ extension String { extension Data { func decode() throws -> T { - return try JSONDecoder().decode(T.self, from: self) + return try jsonDecoder.decode(T.self, from: self) } func decodeArray() throws -> [T] { - return try JSONDecoder().decode([T].self, from: self) + return try jsonDecoder.decode([T].self, from: self) } } diff --git a/LeStorageTests/LeStorageTests.swift b/LeStorageTests/LeStorageTests.swift deleted file mode 100644 index 5e793e7..0000000 --- a/LeStorageTests/LeStorageTests.swift +++ /dev/null @@ -1,36 +0,0 @@ -// -// LeStorageTests.swift -// LeStorageTests -// -// Created by Laurent Morvillier on 02/02/2024. -// - -import XCTest -@testable import LeStorage - -final class LeStorageTests: XCTestCase { - - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - - func testExample() throws { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct results. - // Any test you write for XCTest can be annotated as throws and async. - // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. - // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. - } - - func testPerformanceExample() throws { - // This is an example of a performance test case. - self.measure { - // Put the code you want to measure the time of here. - } - } - -}