Skip to content

Instantly share code, notes, and snippets.

@pixelrevision
Last active May 17, 2022 16:18
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pixelrevision/1daf9c7a4a6c0005804f77c907fded6d to your computer and use it in GitHub Desktop.
Save pixelrevision/1daf9c7a4a6c0005804f77c907fded6d to your computer and use it in GitHub Desktop.
Pascal to Camel json coding
import XCTest
struct SampleCodable: Codable {
let sampleVariable1: String
let sampleVariable2: String
let cAPPEDVariable3: String
let sample: String
}
class PascalJSONCoding: XCTestCase {
let sampleJSON = """
{
"SampleVariable1": "value1",
"SampleVariable2": "value2",
"CAPPEDVariable3": "value3",
"Sample": "value4"
}
"""
func testDecoding() {
guard let jsonData = sampleJSON.data(using: .utf8) else {
fatalError("cannot create data from string")
}
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .custom(JSONDecoder.KeyDecodingStrategy.PascalToCamel)
do {
let output = try decoder.decode(SampleCodable.self, from: jsonData)
XCTAssertEqual(output.sampleVariable1, "value1")
XCTAssertEqual(output.sampleVariable2, "value2")
XCTAssertEqual(output.cAPPEDVariable3, "value3")
XCTAssertEqual(output.sample, "value4")
} catch (let error) {
XCTFail(error.localizedDescription)
}
}
func testEncoding() {
let sample = SampleCodable(
sampleVariable1: "value1",
sampleVariable2: "value2",
cAPPEDVariable3: "value3",
sample: "value4"
)
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .custom(JSONDecoder.KeyDecodingStrategy.CamelToPascal)
do {
let output = try encoder.encode(sample)
let dict = try JSONSerialization.jsonObject(with: output, options: []) as! [String: String]
XCTAssertEqual(dict["SampleVariable1"], sample.sampleVariable1)
XCTAssertEqual(dict["SampleVariable2"], sample.sampleVariable2)
XCTAssertEqual(dict["CAPPEDVariable3"], sample.cAPPEDVariable3)
XCTAssertEqual(dict["Sample"], sample.sample)
} catch (let error) {
XCTFail(error.localizedDescription)
}
}
}
import Foundation
extension JSONDecoder.KeyDecodingStrategy {
// useful for encoding and decoding api calls to and from .NET services
public static let PascalToCamel = { (keys: [CodingKey]) -> CodingKey in
return transformFirst(keys: keys) { $0.lowercased() }
}
public static let CamelToPascal = { (keys: [CodingKey]) -> CodingKey in
return transformFirst(keys: keys) { $0.uppercased() }
}
private static func transformFirst(keys: [CodingKey], _ transformer: (String) -> (String)) -> CodingKey {
guard let last = keys.last?.stringValue else {
return keys.last!
}
let first = transformer(String(last.prefix(1)))
let other = String(last.dropFirst())
return AnyKey(stringValue: first + other)!
}
// from https://developer.apple.com/documentation/foundation/jsondecoder/keydecodingstrategy/custom
private struct AnyKey: CodingKey {
var stringValue: String
var intValue: Int?
init?(stringValue: String) {
self.stringValue = stringValue
self.intValue = nil
}
init?(intValue: Int) {
self.stringValue = String(intValue)
self.intValue = intValue
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment