PascalCase decoding strategy
This commit is contained in:
@@ -7,6 +7,9 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Every `Request` must pass through this `Client`.
|
||||
/// Manages merging `Request` and default headers as well as creating the `URLRequest`.
|
||||
/// Provides its own `JSONDecoder` and `JSONEncoder` with a PascalCase `CodingKey` strategy.
|
||||
public struct Client {
|
||||
// MARK: - Properties
|
||||
private let server: String
|
||||
@@ -20,6 +23,8 @@ public struct Client {
|
||||
self.server = server
|
||||
self.session = session
|
||||
self.defaultHeaders = headers
|
||||
|
||||
decoder.keyDecodingStrategy = .convertFromPascalCase
|
||||
}
|
||||
|
||||
/// When all a client needs is the HTTP status code of an endpoint, this function should be used.
|
||||
@@ -43,7 +48,7 @@ public struct Client {
|
||||
func dataRequest<T>(_ request: any Request) async throws -> T? where T: Codable {
|
||||
let urlRequest = try createRequestObject(for: request)
|
||||
let (data, response) = try await session.data(for: urlRequest)
|
||||
guard let response = response as? HTTPURLResponse else {
|
||||
guard response is HTTPURLResponse else {
|
||||
throw RequestError.invalidResponse
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// PascalCaseKey+KeyDecodingStrategy.swift
|
||||
// JellyKit
|
||||
//
|
||||
// Created by Alex Loren on 10/19/26.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension JSONDecoder.KeyDecodingStrategy {
|
||||
// MARK: - Computed Properties
|
||||
|
||||
/// A key decoding strategy that converts pascal-case keys to camel-case keys.
|
||||
static var convertFromPascalCase: Self {
|
||||
.custom { codingPath in
|
||||
let key = codingPath.last!.stringValue
|
||||
let converted = key.prefix(1).lowercased() + key.dropFirst()
|
||||
return PascalCaseKey(stringValue: converted)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Simply a reusable `CodingKey` for converting PascalCase to camelCase.
|
||||
private struct PascalCaseKey: CodingKey {
|
||||
// MARK: - Properties
|
||||
let stringValue: String
|
||||
let intValue: Int?
|
||||
|
||||
// MARK: - Functions
|
||||
init(stringValue: String) {
|
||||
self.stringValue = stringValue
|
||||
intValue = nil
|
||||
}
|
||||
|
||||
init?(intValue: Int) {
|
||||
stringValue = String(intValue)
|
||||
self.intValue = intValue
|
||||
}
|
||||
}
|
||||
@@ -25,12 +25,4 @@ struct User: Codable {
|
||||
|
||||
/// If not `nil` a request can be made to retreive the profile image for the `User`.
|
||||
var primaryImageTag: String?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id = "Id"
|
||||
case serverId = "ServerId"
|
||||
case name = "Name"
|
||||
case hasPassword = "HasPassword"
|
||||
case primaryImageTag = "PrimaryImageTag"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user