Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: alibaba/HandyJSON
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: ahiho/HandyJSON
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
Able to merge. These branches can be automatically merged.
  • 8 commits
  • 8 files changed
  • 5 contributors

Commits on Aug 26, 2020

  1. add swift_version

    in some 3th part tools, 'pod_target_xcconfig' not work, it's necessary to add the 's.swift_version'
    ycace authored Aug 26, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    609dcb6 View commit details

Commits on Oct 8, 2021

  1. iOS15 int64转string 精度丢失

    wanghao522 authored Oct 8, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    5ce65b4 View commit details

Commits on May 16, 2023

  1. add support for snake to camel

    DragonTnT committed May 16, 2023
    Copy the full SHA
    efb2b89 View commit details

Commits on Feb 28, 2024

  1. Merge pull request #2 from ycace/patch-1

    add swift_version
    jwthanh authored Feb 28, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    2eca8f3 View commit details
  2. Merge pull request #1 from DragonTnT/master

    add support for snake to camel
    jwthanh authored Feb 28, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    ad6a99a View commit details
  3. Merge pull request #3 from wanghao522/master

    iOS15 int64转string 精度丢失
    jwthanh authored Feb 28, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    5e3a00a View commit details

Commits on Mar 8, 2024

  1. fix xcode15 archive failed

    Miles-Matheson committed Mar 8, 2024
    Copy the full SHA
    58fc08a View commit details

Commits on Jun 13, 2024

  1. Merge pull request #4 from Miles-Matheson/master

    fix xcode15 archive failed
    jwthanh authored Jun 13, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    Copy the full SHA
    9f45fab View commit details
1 change: 1 addition & 0 deletions HandyJSON.podspec
Original file line number Diff line number Diff line change
@@ -18,5 +18,6 @@ Pod::Spec.new do |s|
s.watchos.deployment_target = '2.0'
s.tvos.deployment_target = '9.0'

s.swift_version = '5.0'
s.pod_target_xcconfig = { 'SWIFT_VERSION' => '5.0' }
end
12 changes: 6 additions & 6 deletions HandyJSON.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
@@ -1323,7 +1323,7 @@
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "$(SRCROOT)/Source/Info-iOS.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.aliyun.app.HandyJSON;
PRODUCT_NAME = "$(PROJECT_NAME)";
@@ -1347,7 +1347,7 @@
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "$(SRCROOT)/Source/Info-iOS.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.aliyun.app.HandyJSON;
PRODUCT_NAME = "$(PROJECT_NAME)";
@@ -1366,7 +1366,7 @@
DEVELOPMENT_TEAM = QBMN2BBW3K;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = HandyJSONDemo/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.aliyun.app.HandyJSONDemo;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1386,7 +1386,7 @@
DEVELOPMENT_TEAM = QBMN2BBW3K;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = HandyJSONDemo/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.aliyun.app.HandyJSONDemo;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1402,7 +1402,7 @@
BUNDLE_LOADER = "$(TEST_HOST)";
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "Tests/HandyJSONTests/Info-iOS.plist";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.aliyun.app.HandyJSONTests;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1417,7 +1417,7 @@
BUNDLE_LOADER = "$(TEST_HOST)";
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "Tests/HandyJSONTests/Info-iOS.plist";
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.aliyun.app.HandyJSONTests;
PRODUCT_NAME = "$(TARGET_NAME)";
3 changes: 2 additions & 1 deletion Source/BuiltInBasicType.swift
Original file line number Diff line number Diff line change
@@ -136,7 +136,8 @@ extension String: _BuiltInBasicType {
return "false"
}
}
return formatter.string(from: num)
let number = num as NSNumber
return number.stringValue
case _ as NSNull:
return nil
default:
2 changes: 2 additions & 0 deletions Source/Configuration.swift
Original file line number Diff line number Diff line change
@@ -25,6 +25,8 @@ public struct DeserializeOptions: OptionSet {
public let rawValue: Int

public static let caseInsensitive = DeserializeOptions(rawValue: 1 << 0)

public static let snakeToCamel = DeserializeOptions(rawValue: 1 << 1)

public static let defaultOptions: DeserializeOptions = []

68 changes: 57 additions & 11 deletions Source/ExtendCustomModelType.swift
Original file line number Diff line number Diff line change
@@ -13,25 +13,65 @@ public protocol _ExtendCustomModelType: _Transformable {
mutating func willStartMapping()
mutating func mapping(mapper: HelpingMapper)
mutating func didFinishMapping()
func snakeToCamel() -> Bool
}

extension _ExtendCustomModelType {

public mutating func willStartMapping() {}
public mutating func mapping(mapper: HelpingMapper) {}
public mutating func didFinishMapping() {}
public func snakeToCamel() -> Bool {
return HandyJSONConfiguration.deserializeOptions.contains(.snakeToCamel)
}
}

fileprivate func convertKeyIfNeeded(dict: [String: Any]) -> [String: Any] {
if HandyJSONConfiguration.deserializeOptions.contains(.caseInsensitive) {
var newDict = [String: Any]()
fileprivate func convertKeyIfNeeded(dict: [String: Any], snakeToCamel: Bool) -> [String: Any] {
var newDict = [String: Any]()
if snakeToCamel {
dict.forEach({ (kvPair) in
let (key, value) = kvPair
newDict[key.lowercased()] = value
newDict[deserializeSnakeToCamel(input: key)] = value
})
return newDict
} else {
newDict = dict
}
return dict
if HandyJSONConfiguration.deserializeOptions.contains(.caseInsensitive) {
var _newDict = newDict
newDict.forEach({ (kvPair) in
let (key, value) = kvPair
_newDict[key.lowercased()] = value
})
return _newDict
}
return newDict
}

fileprivate func deserializeSnakeToCamel(input: String) -> String {
var result = ""
var capitalizeNext = false
for char in input {
if char == "_" {
capitalizeNext = true
} else if capitalizeNext {
result.append(char.uppercased())
capitalizeNext = false
} else {
result.append(char)
}
}
return result
}

fileprivate func serializeCamelToSnake(input: String) -> String {
var result = ""
for (index,character) in input.enumerated() {
if character.isUppercase && index > 0 {
result.append("_")
}
result.append(character.lowercased())
}
return result
}

fileprivate func getRawValueFrom(dict: [String: Any], property: PropertyInfo, mapper: HelpingMapper) -> Any? {
@@ -90,15 +130,21 @@ fileprivate func readAllChildrenFrom(mirror: Mirror) -> [(String, Any)] {
return result
}

fileprivate func merge(children: [(String, Any)], propertyInfos: [PropertyInfo]) -> [String: (Any, PropertyInfo?)] {
fileprivate func merge(children: [(String, Any)], propertyInfos: [PropertyInfo], snakeToCamel: Bool) -> [String: (Any, PropertyInfo?)] {
var infoDict = [String: PropertyInfo]()
propertyInfos.forEach { (info) in
infoDict[info.key] = info
}

var result = [String: (Any, PropertyInfo?)]()
children.forEach { (child) in
result[child.0] = (child.1, infoDict[child.0])
let key: String
if snakeToCamel {
key = serializeCamelToSnake(input: child.0)
} else {
key = child.0
}
result[key] = (child.1, infoDict[child.0])
}
return result
}
@@ -149,7 +195,7 @@ extension _ExtendCustomModelType {
InternalLogger.logVerbose("instance start at: ", Int(bitPattern: rawPointer))

// process dictionary
let _dict = convertKeyIfNeeded(dict: dict)
let _dict = convertKeyIfNeeded(dict: dict, snakeToCamel: instance.snakeToCamel())

let instanceIsNsObject = instance.isNSObjectType()
let bridgedPropertyList = instance.getBridgedPropertyList()
@@ -220,7 +266,7 @@ extension _ExtendCustomModelType {

mutableObject.mapping(mapper: mapper)

let requiredInfo = merge(children: children, propertyInfos: propertyInfos)
let requiredInfo = merge(children: children, propertyInfos: propertyInfos, snakeToCamel: mutableObject.snakeToCamel())

return _serializeModelObject(instance: mutableObject, properties: requiredInfo, mapper: mapper) as Any
default:
11 changes: 7 additions & 4 deletions Source/Metadata.swift
Original file line number Diff line number Diff line change
@@ -290,11 +290,14 @@ extension Metadata {
var name: String?
var type: Any.Type?
}
for i in 0..<self.numberOfFields {
for i in 0..<self.numberOfFields where fieldRecords[i].mangledTypeName != nil{
let name = fieldRecords[i].fieldName
if let cMangledTypeName = fieldRecords[i].mangledTypeName,
let fieldType = _getTypeByMangledNameInContext(cMangledTypeName, getMangledTypeNameSize(cMangledTypeName), genericContext: self.contextDescriptorPointer, genericArguments: self.genericArgumentVector) {

let cMangledTypeName = fieldRecords[i].mangledTypeName!

let functionMap: [String: () -> Any.Type?] = [
"function": { _getTypeByMangledNameInContext(cMangledTypeName, UInt(getMangledTypeNameSize(cMangledTypeName)), genericContext: self.contextDescriptorPointer, genericArguments: self.genericArgumentVector) }
]
if let function = functionMap["function"],let fieldType = function() {
result.append(Property.Description(key: name, type: fieldType, offset: fieldOffsets[i]))
}
}
13 changes: 13 additions & 0 deletions Tests/HandyJSONTests/BasicTypesInClassTestsFromJSON.swift
Original file line number Diff line number Diff line change
@@ -438,6 +438,19 @@ class BasicTypesInClassTestsFromJSON: XCTestCase {
XCTAssertEqual(mappedObject?.boolImplicitlyUnwrapped, value)
HandyJSONConfiguration.deserializeOptions = .defaultOptions
}

func testSnakeToCamelMappingFromJSON() {
HandyJSONConfiguration.deserializeOptions = .snakeToCamel

let value: Bool = true
let JSONString = "{\"bool_optional\" : \(value)}"

let mappedObject = BasicTypesInClass.deserialize(from: JSONString)

XCTAssertNotNil(mappedObject)
XCTAssertEqual(mappedObject?.boolOptional, value)
HandyJSONConfiguration.deserializeOptions = .defaultOptions
}

func testUpdateExistModel() {
let basicObject = BasicTypesInClass()
21 changes: 21 additions & 0 deletions Tests/HandyJSONTests/OtherFeaturesTest.swift
Original file line number Diff line number Diff line change
@@ -404,4 +404,25 @@ class StructObjectTest: XCTestCase {
let a = A.deserialize(from: jsonString)!
XCTAssertEqual(a.upperName, "HANDYJSON")
}

func testSnakeToCamelForStruct() {
struct A: HandyJSON {
var snakeKey: String?

func snakeToCamel() -> Bool {
return true
}
}

struct B: HandyJSON {
var camelKey: String?
}

let jsonString1 = "{\"snake_key\":\"HandyJson\"}"
let jsonString2 = "{\"camelKey\":\"HandyJson\"}"
let a = A.deserialize(from: jsonString1)!
let b = B.deserialize(from: jsonString2)!
XCTAssertEqual(a.snakeKey, "HandyJson")
XCTAssertEqual(b.camelKey, "HandyJson")
}
}