From b7613b58a42fbe86a60b52db9e48170281ac07be Mon Sep 17 00:00:00 2001 From: Le Van Long Date: Sat, 22 Sep 2018 02:50:37 +0700 Subject: [PATCH] present null for nil property --- README.md | 12 ++++++++++++ Source/ExtendCustomModelType.swift | 10 +++++++++- Source/HelpingMapper.swift | 13 +++++++++++++ Tests/HandyJSONTests/OtherFeaturesTest.swift | 15 +++++++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e9732f0..af7d9eb 100644 --- a/README.md +++ b/README.md @@ -683,7 +683,19 @@ class BasicTypes: HandyJSON { } ``` +## Q: How to present a `null` value of `nil` property when serialize to JSON? +In `mapping(mapper: HelpingMapper)`, use `mapper.nullPresent` to apply null present for property + +```swift +class Animal: HandyJSON { + var name: String? + var owner: String? + func mapping(mapper: HelpingMapper) { + mapper.nullPresent(self.owner) + } +} +``` # License diff --git a/Source/ExtendCustomModelType.swift b/Source/ExtendCustomModelType.swift index 59bb7b0..9997c96 100644 --- a/Source/ExtendCustomModelType.swift +++ b/Source/ExtendCustomModelType.swift @@ -235,7 +235,7 @@ extension _ExtendCustomModelType { for (key, property) in properties { var realKey = key var realValue = property.0 - + var useNullValueIfNeeded = false if let info = property.1 { if info.bridged, let _value = (instance as! NSObject).value(forKey: key) { realValue = _value @@ -245,6 +245,10 @@ extension _ExtendCustomModelType { continue } + if mapper.propertyPresentNullValue(key: Int(bitPattern: info.address)) { + useNullValueIfNeeded = true + } + if let mappingHandler = mapper.getMappingHandler(key: Int(bitPattern: info.address)) { // if specific key is set, replace the label if let mappingPaths = mappingHandler.mappingPaths, mappingPaths.count > 0 { @@ -266,6 +270,10 @@ extension _ExtendCustomModelType { dict[realKey] = result continue } + else if useNullValueIfNeeded { + dict[realKey] = NSNull() + continue + } } InternalLogger.logDebug("The value for key: \(key) is not transformable type") diff --git a/Source/HelpingMapper.swift b/Source/HelpingMapper.swift index 9b1f454..a2f8a7f 100644 --- a/Source/HelpingMapper.swift +++ b/Source/HelpingMapper.swift @@ -85,6 +85,7 @@ public class HelpingMapper { private var mappingHandlers = [Int: MappingPropertyHandler]() private var excludeProperties = [Int]() + private var nullPresentProperties = [Int]() internal func getMappingHandler(key: Int) -> MappingPropertyHandler? { return self.mappingHandlers[key] @@ -94,6 +95,10 @@ public class HelpingMapper { return self.excludeProperties.contains(key) } + internal func propertyPresentNullValue(key: Int) -> Bool { + return self.nullPresentProperties.contains(key) + } + public func specify(property: inout T, name: String) { self.specify(property: &property, name: name, converter: nil) } @@ -128,6 +133,14 @@ public class HelpingMapper { self._exclude(property: &property) } + public func nullPresent(property: inout T) { + let pointer = withUnsafePointer(to: &property, { return $0 }) + let iPointer = Int(bitPattern: pointer) + if !self.excludeProperties.contains(iPointer) && !nullPresentProperties.contains(iPointer) { + nullPresentProperties.append(iPointer) + } + } + fileprivate func addCustomMapping(key: Int, mappingInfo: MappingPropertyHandler) { self.mappingHandlers[key] = mappingInfo } diff --git a/Tests/HandyJSONTests/OtherFeaturesTest.swift b/Tests/HandyJSONTests/OtherFeaturesTest.swift index 06e6505..8f47243 100644 --- a/Tests/HandyJSONTests/OtherFeaturesTest.swift +++ b/Tests/HandyJSONTests/OtherFeaturesTest.swift @@ -404,4 +404,19 @@ class StructObjectTest: XCTestCase { let a = A.deserialize(from: jsonString)! XCTAssertEqual(a.upperName, "HANDYJSON") } + + func testNullPresentValue() { + class A: HandyJSON { + var name: String? + required init() {} + + func mapping(mapper: HelpingMapper) { + mapper.nullPresent(property: &self.name) + } + } + + let a = A() + let jsonString = a.toJSONString()! + XCTAssertEqual(jsonString, "{\"name\":null}") + } }