Skip to content

Commit a6d089d

Browse files
committed
keep default model value for optimization
1 parent 044e226 commit a6d089d

File tree

4 files changed

+100
-4
lines changed

4 files changed

+100
-4
lines changed

KakaJSON/Convert/Convertible.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,9 @@ extension Convertible {
264264
}
265265

266266
// try to convert newValue to propertyType
267-
guard let value = Values.value(newValue, propertyType) else {
267+
guard let value = Values.value(newValue,
268+
propertyType,
269+
property.get(from: model)) else {
268270
property.set(newValue, for: model)
269271
continue
270272
}

KakaJSON/Convert/Values.swift

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,17 @@ import CoreGraphics
1212
#endif
1313

1414
public struct Values {
15-
static func value(_ val: Any?, _ type: Any.Type) -> Any? {
15+
static func value(_ val: Any?,
16+
_ type: Any.Type,
17+
_ defaultValue: @autoclosure () -> Any? = nil) -> Any? {
1618
guard let v = val.kj_value else { return nil }
1719
if Swift.type(of: v) == type { return v }
1820
if v is NSNull { return nil }
1921

2022
switch type {
2123
case is NumberValue.Type: return _number(v, type)
2224
case is StringValue.Type: return _string(v, type)
23-
case let ct as Convertible.Type: return _model(v, ct)
25+
case let ct as Convertible.Type: return _model(v, ct, defaultValue)
2426
case is DateValue.Type: return _date(v)
2527
case is ArrayValue.Type: return _array(v, type)
2628
case is DictionaryValue.Type: return _dictionary(v, type)
@@ -73,8 +75,14 @@ private extension Values {
7375
return lower
7476
}
7577

76-
static func _model(_ value: Any, _ type: Convertible.Type) -> Convertible? {
78+
static func _model(_ value: Any,
79+
_ type: Convertible.Type,
80+
_ defaultValue: () -> Any?) -> Convertible? {
7781
guard let json = value as? [String: Any] else { return nil }
82+
if var model = defaultValue().kj_value as? Convertible {
83+
model.kj_convert(from: json)
84+
return model
85+
}
7886
return json.kj.model(type: type)
7987
}
8088

KakaJSONTests/JSON_To_Model/JTM_03_NestedModel.swift

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,48 @@ class JTM_03_NestedModel: XCTestCase {
7272
XCTAssert(person.dogs?["dog1"]?.name == dogs[1].name)
7373
XCTAssert(person.dogs?["dog1"]?.age == dogs[1].age)
7474
}
75+
76+
func testDefaultValue() {
77+
struct Car: Convertible {
78+
var name: String = ""
79+
var price: Double = 0.0
80+
}
81+
82+
class Dog: Convertible {
83+
var name: String = ""
84+
var age: Int = 0
85+
required init() {}
86+
init(name: String, age: Int) {
87+
self.name = name
88+
self.age = age
89+
}
90+
}
91+
92+
struct Person: Convertible {
93+
var name: String = ""
94+
// KakaJSON will use your defaultValue instead of creating a new model
95+
// KakaJSON will not creat a new model again if you already have a default model value
96+
var car: Car = Car(name: "Bently", price: 106.5)
97+
var dog: Dog = Dog(name: "Larry", age: 5)
98+
}
99+
100+
let json: [String: Any] = [
101+
"name": "Jake",
102+
"car": ["price": 305.6],
103+
"dog": ["name": "Wangwang"]
104+
]
105+
106+
let person = json.kj.model(Person.self)
107+
XCTAssert(person.name == "Jake")
108+
// keep defaultValue
109+
XCTAssert(person.car.name == "Bently")
110+
// use value from json
111+
XCTAssert(person.car.price == 305.6)
112+
// use value from json
113+
XCTAssert(person.dog.name == "Wangwang")
114+
// keep defaultValue
115+
XCTAssert(person.dog.age == 5)
116+
}
75117

76118
func testRecursive() {
77119
class Person: Convertible {

README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ Or you can login Xcode with your GitHub account. just search **KakaJSON**.
5050
- [JSONData](#jsondata)
5151
- [Nested Model 1](#nested-model-1)
5252
- [Nested Model 2](#nested-model-2)
53+
- [Nested Model 3](#nested-model-3)
5354
- [Recursive](#recursive)
5455
- [Generic](#generic)
5556
- [Model Array](#model-array)
@@ -487,6 +488,49 @@ XCTAssert(book?.name == "Fast C++")
487488
XCTAssert(book?.price == 666.6)
488489
```
489490

491+
### Nested Model3
492+
```swift
493+
struct Car: Convertible {
494+
var name: String = ""
495+
var price: Double = 0.0
496+
}
497+
498+
class Dog: Convertible {
499+
var name: String = ""
500+
var age: Int = 0
501+
required init() {}
502+
init(name: String, age: Int) {
503+
self.name = name
504+
self.age = age
505+
}
506+
}
507+
508+
struct Person: Convertible {
509+
var name: String = ""
510+
// KakaJSON will use your defaultValue instead of creating a new model
511+
// KakaJSON will not creat a new model again if you already have a default model value
512+
var car: Car = Car(name: "Bently", price: 106.5)
513+
var dog: Dog = Dog(name: "Larry", age: 5)
514+
}
515+
516+
let json: [String: Any] = [
517+
"name": "Jake",
518+
"car": ["price": 305.6],
519+
"dog": ["name": "Wangwang"]
520+
]
521+
522+
let person = json.kj.model(Person.self)
523+
XCTAssert(person.name == "Jake")
524+
// keep defaultValue
525+
XCTAssert(person.car.name == "Bently")
526+
// use value from json
527+
XCTAssert(person.car.price == 305.6)
528+
// use value from json
529+
XCTAssert(person.dog.name == "Wangwang")
530+
// keep defaultValue
531+
XCTAssert(person.dog.age == 5)
532+
```
533+
490534
### Recursive
491535
```swift
492536
class Person: Convertible {

0 commit comments

Comments
 (0)