Skip to content

Commit

Permalink
keep default model value for optimization
Browse files Browse the repository at this point in the history
  • Loading branch information
CoderMJLee committed Aug 28, 2019
1 parent 044e226 commit a6d089d
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 4 deletions.
4 changes: 3 additions & 1 deletion KakaJSON/Convert/Convertible.swift
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,9 @@ extension Convertible {
}

// try to convert newValue to propertyType
guard let value = Values.value(newValue, propertyType) else {
guard let value = Values.value(newValue,
propertyType,
property.get(from: model)) else {
property.set(newValue, for: model)
continue
}
Expand Down
14 changes: 11 additions & 3 deletions KakaJSON/Convert/Values.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,17 @@ import CoreGraphics
#endif

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

switch type {
case is NumberValue.Type: return _number(v, type)
case is StringValue.Type: return _string(v, type)
case let ct as Convertible.Type: return _model(v, ct)
case let ct as Convertible.Type: return _model(v, ct, defaultValue)
case is DateValue.Type: return _date(v)
case is ArrayValue.Type: return _array(v, type)
case is DictionaryValue.Type: return _dictionary(v, type)
Expand Down Expand Up @@ -73,8 +75,14 @@ private extension Values {
return lower
}

static func _model(_ value: Any, _ type: Convertible.Type) -> Convertible? {
static func _model(_ value: Any,
_ type: Convertible.Type,
_ defaultValue: () -> Any?) -> Convertible? {
guard let json = value as? [String: Any] else { return nil }
if var model = defaultValue().kj_value as? Convertible {
model.kj_convert(from: json)
return model
}
return json.kj.model(type: type)
}

Expand Down
42 changes: 42 additions & 0 deletions KakaJSONTests/JSON_To_Model/JTM_03_NestedModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,48 @@ class JTM_03_NestedModel: XCTestCase {
XCTAssert(person.dogs?["dog1"]?.name == dogs[1].name)
XCTAssert(person.dogs?["dog1"]?.age == dogs[1].age)
}

func testDefaultValue() {
struct Car: Convertible {
var name: String = ""
var price: Double = 0.0
}

class Dog: Convertible {
var name: String = ""
var age: Int = 0
required init() {}
init(name: String, age: Int) {
self.name = name
self.age = age
}
}

struct Person: Convertible {
var name: String = ""
// KakaJSON will use your defaultValue instead of creating a new model
// KakaJSON will not creat a new model again if you already have a default model value
var car: Car = Car(name: "Bently", price: 106.5)
var dog: Dog = Dog(name: "Larry", age: 5)
}

let json: [String: Any] = [
"name": "Jake",
"car": ["price": 305.6],
"dog": ["name": "Wangwang"]
]

let person = json.kj.model(Person.self)
XCTAssert(person.name == "Jake")
// keep defaultValue
XCTAssert(person.car.name == "Bently")
// use value from json
XCTAssert(person.car.price == 305.6)
// use value from json
XCTAssert(person.dog.name == "Wangwang")
// keep defaultValue
XCTAssert(person.dog.age == 5)
}

func testRecursive() {
class Person: Convertible {
Expand Down
44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Or you can login Xcode with your GitHub account. just search **KakaJSON**.
- [JSONData](#jsondata)
- [Nested Model 1](#nested-model-1)
- [Nested Model 2](#nested-model-2)
- [Nested Model 3](#nested-model-3)
- [Recursive](#recursive)
- [Generic](#generic)
- [Model Array](#model-array)
Expand Down Expand Up @@ -487,6 +488,49 @@ XCTAssert(book?.name == "Fast C++")
XCTAssert(book?.price == 666.6)
```

### Nested Model3
```swift
struct Car: Convertible {
var name: String = ""
var price: Double = 0.0
}

class Dog: Convertible {
var name: String = ""
var age: Int = 0
required init() {}
init(name: String, age: Int) {
self.name = name
self.age = age
}
}

struct Person: Convertible {
var name: String = ""
// KakaJSON will use your defaultValue instead of creating a new model
// KakaJSON will not creat a new model again if you already have a default model value
var car: Car = Car(name: "Bently", price: 106.5)
var dog: Dog = Dog(name: "Larry", age: 5)
}

let json: [String: Any] = [
"name": "Jake",
"car": ["price": 305.6],
"dog": ["name": "Wangwang"]
]

let person = json.kj.model(Person.self)
XCTAssert(person.name == "Jake")
// keep defaultValue
XCTAssert(person.car.name == "Bently")
// use value from json
XCTAssert(person.car.price == 305.6)
// use value from json
XCTAssert(person.dog.name == "Wangwang")
// keep defaultValue
XCTAssert(person.dog.age == 5)
```

### Recursive
```swift
class Person: Convertible {
Expand Down

0 comments on commit a6d089d

Please sign in to comment.