Skip to content

Commit bfcb6c8

Browse files
committed
codingSrategy fix and sample
1 parent ca58c87 commit bfcb6c8

File tree

4 files changed

+47
-10
lines changed

4 files changed

+47
-10
lines changed

README.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,8 +189,6 @@ perl -p -e "s/($KEYWORDS)/ warning: \$1/"
189189

190190
You can install this by adding the following line to your Podfile:
191191

192-
⚠️WARNING: Swift 4 or later is required ⚠️
193-
194192
```
195193
pod "Stuff/Codable"
196194
```
@@ -216,7 +214,7 @@ And here you can see how you can use these Stuff/Codable functions:
216214

217215
```swift
218216
func test() {
219-
let initialObject = TestCodable(naam: "Edwin", id: 1)
217+
let initialObject = TestCodable(naam: "Edwin", id: 1, testField: "tst")
220218

221219
guard let json = initialObject.toJsonString() else {
222220
print("Could not create json from object")
@@ -245,11 +243,18 @@ func test() {
245243
return
246244
}
247245
print("inner object from json \(String(describing: innerObject))")
246+
247+
guard let custom = try TestCodable(json: "{\"Naam\":\"UpperN\", \"Id\":5, \"Test_field\":\"lowerSnake\"}", keyPath: nil, codingStrategy: customCodingStragegy) else {
248+
print("Could not custom case convert")
249+
return
250+
}
251+
print("read object with custom key coding from json to \(String(describing:
248252
}
249253
250254
struct TestCodable : Codable {
251255
var naam: String?
252256
var id: Int?
257+
var testField: String?
253258
}
254259
```
255260

Source/Codable/Codable.swift

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,28 @@ enum CodingError : Error {
1010
case RuntimeError(String)
1111
}
1212

13+
struct AnyKey: CodingKey {
14+
var stringValue: String
15+
var intValue: Int?
16+
17+
init(stringValue: String) {
18+
self.stringValue = stringValue
19+
self.intValue = nil
20+
}
21+
22+
init(intValue: Int) {
23+
self.stringValue = String(intValue)
24+
self.intValue = intValue
25+
}
26+
}
27+
28+
public var customCodingStragegy: JSONDecoder.KeyDecodingStrategy = .custom { keys in
29+
let lastComponent = keys.last!.stringValue
30+
let snakeCased = lastComponent.split(separator: "_").map { $0.prefix(1).uppercased() + $0.dropFirst() }.reduce("") { $0 + $1}
31+
let lowerFirst = snakeCased.prefix(1).lowercased() + snakeCased.dropFirst()
32+
return AnyKey(stringValue: lowerFirst)
33+
}
34+
1335
public extension Encodable {
1436
/**
1537
Convert this object to json data
@@ -94,9 +116,9 @@ public extension Decodable {
94116
- parameter json: The json string
95117
- parameter keyPath: for if you want something else than the root object
96118
*/
97-
init(json: String, keyPath: String? = nil) throws {
119+
init(json: String, keyPath: String? = nil, codingStrategy: JSONDecoder.KeyDecodingStrategy = .convertFromSnakeCase) throws {
98120
guard let data = json.data(using: .utf8) else { throw CodingError.RuntimeError("cannot create data from string") }
99-
try self.init(data: data, keyPath: keyPath)
121+
try self.init(data: data, keyPath: keyPath, codingStrategy: codingStrategy)
100122
}
101123

102124
/**
@@ -105,9 +127,9 @@ public extension Decodable {
105127
- parameter data: The json data
106128
- parameter keyPath: for if you want something else than the root object
107129
*/
108-
init(data: Data, keyPath: String? = nil, codingStragegy: JSONDecoder.KeyDecodingStrategy = .convertFromSnakeCase) throws {
130+
init(data: Data, keyPath: String? = nil, codingStrategy: JSONDecoder.KeyDecodingStrategy = .convertFromSnakeCase) throws {
109131
let decoder = JSONDecoder()
110-
decoder.keyDecodingStrategy = .convertFromSnakeCase
132+
decoder.keyDecodingStrategy = codingStrategy
111133
if let keyPath = keyPath {
112134
let topLevel = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers)
113135
guard let nestedJson = (topLevel as AnyObject).value(forKeyPath: keyPath) else { throw CodingError.RuntimeError("Cannot decode data to object") }

Stuff.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = "Stuff"
3-
s.version = "0.6.1"
3+
s.version = "0.7.0"
44
s.summary = "Too small for a library, too important to just forget"
55

66
s.description = <<-EOS

StuffTests/CodableStuffTests.swift

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import XCTest
1313
class CodingStuffTests: XCTestCase {
1414

1515
func test() {
16-
let initialObject = TestCodable(naam: "Edwin", id: 1)
16+
let initialObject = TestCodable(naam: "Edwin", id: 1, testField: "tst")
1717

1818
guard let json = initialObject.toJsonString() else {
1919
print("Could not create json from object")
@@ -46,7 +46,16 @@ class CodingStuffTests: XCTestCase {
4646
return
4747
}
4848
print("inner object from json \(String(describing: innerObject))")
49-
49+
50+
do {
51+
let custom = try TestCodable(json: "{\"Naam\":\"UN\", \"Id\":5, \"Test_field\":\"tst\"}", keyPath: nil, codingStrategy: customCodingStragegy)
52+
print("read object with custom key coding from json to \(String(describing: custom))")
53+
} catch {
54+
print("Could not custom case convert \(error)")
55+
assertionFailure()
56+
return
57+
}
58+
5059
do {
5160
try initialObject.saveToDocuments("myFile.dat")
5261
} catch {
@@ -80,4 +89,5 @@ class CodingStuffTests: XCTestCase {
8089
struct TestCodable : Codable {
8190
var naam: String?
8291
var id: Int?
92+
var testField: String?
8393
}

0 commit comments

Comments
 (0)