Skip to content

Commit 3e2aab3

Browse files
committed
add dynamicMemberLookup support
1 parent 2513e01 commit 3e2aab3

4 files changed

Lines changed: 79 additions & 28 deletions

File tree

Demo/main.swift

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,27 @@ let dict = ["data": ["man": ["age": 10, "name": "Peter", "height": 180.0, "extra
2020

2121
// MARK: - JSONMapper
2222
print("-- JSONMapper --")
23-
let map = JSONMapper(data: dict)
23+
let json = JSONMapper(raw: dict)
2424
// 直接获取
25-
if let value = map["data"]["man"]["age"].intValue {
25+
if let value = json["data"]["man"]["age"].intValue {
2626
print(value)
2727
}
2828
// 使用Key获取
29-
if let value: Double = map["data"]["man"]["height"].value() {
29+
if let value = json["data"]["man"]["height"].value(type: Double.self) {
3030
print(value)
3131
}
32+
33+
// 使用 dynamicMemberLookup 获取
34+
if let value = json.data.man.height.value(type: Double.self) {
35+
print(value)
36+
}
37+
3238
// 使用Keypath获取
33-
if let value = map.value(keyPath: "data.man.name", type: String.self) {
39+
if let value = json.value(keyPath: "data.man.name", type: String.self) {
3440
print(value)
3541
}
3642

37-
if let manDict: Any = map["data"]["man"].value() {
43+
if let manDict: Any = json["data"]["man"].value() {
3844
let data = try JSONSerialization.data(withJSONObject: manDict, options: [])
3945
let man = try JSONDecoder().decode(Human.self, from: data)
4046
if let value = man.extra.arrayValue {
@@ -45,8 +51,15 @@ if let manDict: Any = map["data"]["man"].value() {
4551

4652
}
4753
}
48-
// Output
49-
// 10
50-
// ["iPhone", "Blackberry", "Xiaomi"]
51-
// [Optional(123), Optional("123"), Optional([Optional(123)]), Optional(["123": 123]), Optional(true)]
52-
// 123
54+
55+
//
56+
// Output:
57+
//
58+
//-- JSONMapper --
59+
//10
60+
//180.0
61+
//180.0
62+
//Peter
63+
//[Optional(123), Optional("123"), Optional([Optional(123)]), Optional(["123": 123]), Optional(true)]
64+
//123
65+
//Program ended with exit code: 0

JsonMapper/JsonMapper.swift

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import Foundation
1010

11+
@dynamicMemberLookup
1112
public enum JSONElement: Codable {
1213

1314
case null
@@ -148,8 +149,17 @@ public enum JSONElement: Codable {
148149
let data = try JSONEncoder().encode(self)
149150
return try JSONDecoder().decode(T.self, from: data)
150151
}
152+
153+
public subscript(dynamicMember member: String) -> JSONElement {
154+
if case .object(let value) = self {
155+
return value[member] ?? .null
156+
}
157+
return .null
158+
}
151159
}
152160

161+
162+
@dynamicMemberLookup
153163
public struct JSONMapper {
154164

155165
private var originData: Any?
@@ -175,11 +185,19 @@ public struct JSONMapper {
175185
self.originData = obj
176186
}
177187

178-
public init(data: Any?) {
179-
self.originData = data
188+
public init(data: Data) {
189+
guard let obj = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) else {
190+
self.originData = nil
191+
return
192+
}
193+
self.originData = obj
194+
}
195+
196+
public init(raw: Any?) {
197+
self.originData = raw
180198
}
181199

182-
public func value<T>() -> T? {
200+
public func value<T>(type: T.Type = T.self) -> T? {
183201
return originData as? T
184202
}
185203

@@ -194,15 +212,21 @@ public struct JSONMapper {
194212

195213

196214
public subscript(key: String) -> JSONMapper {
197-
return JSONMapper(data: (originData as? [String: Any])?[key])
215+
return JSONMapper(raw: (originData as? [String: Any])?[key])
198216
}
199217

200218
public subscript(index: Int) -> JSONMapper {
201219
guard let array = originData as? [Any],
202220
index < array.count else {
203-
return JSONMapper(data: nil)
221+
return JSONMapper(raw: nil)
204222
}
205-
return JSONMapper(data: array[index])
223+
return JSONMapper(raw: array[index])
224+
}
225+
226+
public subscript(dynamicMember member: String) -> JSONMapper {
227+
guard let v = self.originData,
228+
let dict = v as? [String: Any] else { return JSONMapper(raw: nil) }
229+
return JSONMapper(raw: dict[member])
206230
}
207231

208232
}

README.md

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
Because `Any` can't be used in `Codable`, it can be replaced with `JSONElement` for properties of type `Any`.
66

7+
8+
79
# Example
810

911
```swift
@@ -20,21 +22,27 @@ let dict = ["data": ["man": ["age": 10, "name": "Peter", "height": 180.0, "extra
2022

2123
// MARK: - JSONMapper
2224
print("-- JSONMapper --")
23-
let map = JSONMapper(data: dict)
25+
let json = JSONMapper(raw: dict)
2426
// 直接获取
25-
if let value = map["data"]["man"]["age"].intValue {
27+
if let value = json["data"]["man"]["age"].intValue {
2628
print(value)
2729
}
2830
// 使用Key获取
29-
if let value: Double = map["data"]["man"]["height"].value() {
31+
if let value = json["data"]["man"]["height"].value(type: Double.self) {
3032
print(value)
3133
}
34+
35+
// 使用 dynamicMemberLookup 获取
36+
if let value = json.data.man.height.value(type: Double.self) {
37+
print(value)
38+
}
39+
3240
// 使用Keypath获取
33-
if let value = map.value(keyPath: "data.man.name", type: String.self) {
41+
if let value = json.value(keyPath: "data.man.name", type: String.self) {
3442
print(value)
3543
}
3644

37-
if let manDict: Any = map["data"]["man"].value() {
45+
if let manDict: Any = json["data"]["man"].value() {
3846
let data = try JSONSerialization.data(withJSONObject: manDict, options: [])
3947
let man = try JSONDecoder().decode(Human.self, from: data)
4048
if let value = man.extra.arrayValue {
@@ -45,12 +53,18 @@ if let manDict: Any = map["data"]["man"].value() {
4553

4654
}
4755
}
48-
// Output
49-
// 10
50-
// 180.0
51-
// Peter
52-
// [Optional(123), Optional("123"), Optional([Optional(123)]), Optional(["123": 123]), Optional(true)]
53-
// 123
56+
57+
//
58+
// Output:
59+
//
60+
//-- JSONMapper --
61+
//10
62+
//180.0
63+
//180.0
64+
//Peter
65+
//[Optional(123), Optional("123"), Optional([Optional(123)]), Optional(["123": 123]), Optional(true)]
66+
//123
67+
//Program ended with exit code: 0
5468

5569

5670

TKJsonMapper.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 = 'TKJsonMapper'
3-
s.version = '1.0.0'
3+
s.version = '1.1.0'
44

55
s.license = { :type => 'MIT', :file => 'LICENSE' }
66
s.summary = 'JSONMapper/JSONElement makes it easier and safer to use JSON'

0 commit comments

Comments
 (0)