Skip to content

Commit

Permalink
Fix infinit loops
Browse files Browse the repository at this point in the history
  • Loading branch information
Arnaud Schildknecht committed Jul 16, 2019
1 parent 8d07d66 commit 44e9ab1
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 43 deletions.
17 changes: 7 additions & 10 deletions JSONUtilities.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -305,12 +305,12 @@
TargetAttributes = {
4FE3C0241C00EDE900607CC4 = {
CreatedOnToolsVersion = 7.1;
LastSwiftMigration = 0900;
LastSwiftMigration = 1020;
ProvisioningStyle = Manual;
};
4FE3C02E1C00EDE900607CC4 = {
CreatedOnToolsVersion = 7.1;
LastSwiftMigration = 0900;
LastSwiftMigration = 1020;
};
};
};
Expand All @@ -319,6 +319,7 @@
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
);
mainGroup = 4FE3C01B1C00EDE900607CC4;
Expand Down Expand Up @@ -550,8 +551,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.2;
SWIFT_VERSION = 5.0;
};
name = Debug;
};
Expand All @@ -570,8 +570,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.2;
SWIFT_VERSION = 5.0;
};
name = Release;
};
Expand All @@ -583,8 +582,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "com.TechBrewers-LTD.JSONUtilitiesTests";
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx appletvos appletvsimulator";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 5.0;
};
name = Debug;
};
Expand All @@ -597,8 +595,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx appletvos appletvsimulator";
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
SWIFT_VERSION = 5.0;
};
name = Release;
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
8 changes: 4 additions & 4 deletions Sources/JSONUtilities/Deprecations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,24 +99,24 @@ public extension Dictionary where Key: StringProtocol {
// MARK: RawRepresentable type

@available(*, deprecated:3.0.0, renamed: "json(atKeyPath:)")
public func jsonKey<ReturnType: RawRepresentable>(_ key: Key) throws -> ReturnType where ReturnType.RawValue:JSONRawType {
public func jsonKey<ReturnType: RawRepresentable>(_ key: Key) throws -> ReturnType where ReturnType.RawValue: JSONRawType {
return try json(atKeyPath: key)
}

@available(*, deprecated:3.0.0, renamed: "json(atKeyPath:)")
public func jsonKey<ReturnType: RawRepresentable>(_ key: Key) -> ReturnType? where ReturnType.RawValue:JSONRawType {
public func jsonKey<ReturnType: RawRepresentable>(_ key: Key) -> ReturnType? where ReturnType.RawValue: JSONRawType {
return json(atKeyPath: key)
}

// MARK: [RawRepresentable] type

@available(*, deprecated:3.0.0, renamed: "json(atKeyPath:)")
public func jsonKey<ReturnType: RawRepresentable>(_ key: Key) throws -> [ReturnType] where ReturnType.RawValue:JSONRawType {
public func jsonKey<ReturnType: RawRepresentable>(_ key: Key) throws -> [ReturnType] where ReturnType.RawValue: JSONRawType {
return try json(atKeyPath: key)
}

@available(*, deprecated:3.0.0, renamed: "json(atKeyPath:)")
public func jsonKey<ReturnType: RawRepresentable>(_ key: Key) -> [ReturnType]? where ReturnType.RawValue:JSONRawType {
public func jsonKey<ReturnType: RawRepresentable>(_ key: Key) -> [ReturnType]? where ReturnType.RawValue: JSONRawType {
return json(atKeyPath: key)
}

Expand Down
96 changes: 71 additions & 25 deletions Sources/JSONUtilities/Dictionary+JSONKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import Foundation

/// Protocol used for defining the valid JSON types, i.e. Int, Double, Float, String and Bool
public protocol JSONRawType {}
extension Int : JSONRawType {}
extension Double : JSONRawType {}
extension Float : JSONRawType {}
extension String : JSONRawType {}
extension Bool : JSONRawType {}
extension Int: JSONRawType {}
extension Double: JSONRawType {}
extension Float: JSONRawType {}
extension String: JSONRawType {}
extension Bool: JSONRawType {}

// Simple protocol used to extend a JSONDictionary
public protocol StringProtocol {
Expand All @@ -38,7 +38,8 @@ extension Dictionary where Key: StringProtocol {

/// Decode an optional JSON raw type
public func json<T: JSONRawType>(atKeyPath keyPath: Key) -> T? {
return try? json(atKeyPath: keyPath)
return try? getValue(atKeyPath: keyPath)
// return try? json(atKeyPath: keyPath)
}

// MARK: [JSONRawType] type
Expand All @@ -50,7 +51,8 @@ extension Dictionary where Key: StringProtocol {

/// Decode an Array of optional JSON raw types
public func json<T: JSONRawType>(atKeyPath keyPath: Key, invalidItemBehaviour: InvalidItemBehaviour<T> = .remove) -> [T]? {
return try? self.json(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour)
return try? decodeArray(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour, decode: getValue)
// return try? self.json(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour)
}

// MARK: [String: Any] type
Expand All @@ -74,7 +76,8 @@ extension Dictionary where Key: StringProtocol {

/// Decodes as a raw ictionary array with an optional key
public func json(atKeyPath keyPath: Key, invalidItemBehaviour: InvalidItemBehaviour<JSONDictionary> = .remove) -> [JSONDictionary]? {
return try? self.json(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour)
return try? decodeArray(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour, decode: getValue)
// return try? self.json(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour)
}

// MARK: [String: JSONObjectConvertible] type
Expand All @@ -88,7 +91,10 @@ extension Dictionary where Key: StringProtocol {

/// Decodes an optional dictionary
public func json<T: JSONObjectConvertible>(atKeyPath keyPath: Key, invalidItemBehaviour: InvalidItemBehaviour<T> = .remove) -> [String: T]? {
return try? json(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour) as [String: T]
return try? decodeDictionary(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour) { jsonDictionary, key in
return try jsonDictionary.json(atKeyPath: key) as T
}
// return try? json(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour) as [String: T]
}

// MARK: [String: JSONRawType] type
Expand All @@ -102,7 +108,10 @@ extension Dictionary where Key: StringProtocol {

/// Decodes an optional dictionary
public func json<T: JSONRawType>(atKeyPath keyPath: Key, invalidItemBehaviour: InvalidItemBehaviour<T> = .remove) -> [String: T]? {
return try? json(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour) as [String: T]
return try? decodeDictionary(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour) { jsonDictionary, key in
return try jsonDictionary.json(atKeyPath: key) as T
}
// return try? json(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour) as [String: T]
}

// MARK: [String: JSONPrimitiveConvertible] type
Expand All @@ -116,7 +125,10 @@ extension Dictionary where Key: StringProtocol {

/// Decodes an optional dictionary
public func json<T: JSONPrimitiveConvertible>(atKeyPath keyPath: Key, invalidItemBehaviour: InvalidItemBehaviour<T> = .remove) -> [String: T]? {
return try? json(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour) as [String: T]
return try? decodeDictionary(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour) { jsonDictionary, key in
return try jsonDictionary.json(atKeyPath: key) as T
}
// return try? json(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour) as [String: T]
}

// MARK: Decodable types
Expand All @@ -143,64 +155,90 @@ extension Dictionary where Key: StringProtocol {

/// Decode an Array of optional Decodable objects
public func json<T: JSONObjectConvertible>(atKeyPath keyPath: Key, invalidItemBehaviour: InvalidItemBehaviour<T> = .remove) -> [T]? {
return try? json(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour)
return try? decodeArray(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour) { keyPath, jsonArray, value in
let jsonDictionary: JSONDictionary = try getValue(atKeyPath: keyPath, array: jsonArray, value: value)
return try T(jsonDictionary: jsonDictionary)
}
// return try? json(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour)
}

// MARK: RawRepresentable type

/// Decode a mandatory RawRepresentable
public func json<T: RawRepresentable>(atKeyPath keyPath: Key) throws -> T where T.RawValue:JSONRawType {
public func json<T: RawRepresentable>(atKeyPath keyPath: Key) throws -> T where T.RawValue: JSONRawType {
let rawValue: T.RawValue = try getValue(atKeyPath: keyPath)

guard let value = T(rawValue:rawValue) else {
guard let value = T(rawValue: rawValue) else {
throw DecodingError(dictionary: self, keyPath: keyPath, expectedType: T.self, value: rawValue, reason: .incorrectRawRepresentableRawValue)
}

return value
}

/// Decode an optional RawRepresentable
public func json<T: RawRepresentable>(atKeyPath keyPath: Key) -> T? where T.RawValue:JSONRawType {
return try? json(atKeyPath: keyPath)
public func json<T: RawRepresentable>(atKeyPath keyPath: Key) -> T? where T.RawValue: JSONRawType {
let rawValue: T.RawValue? = try? getValue(atKeyPath: keyPath)

guard let rawVal = rawValue,
let value = T(rawValue: rawVal) else {
return nil
}
return value
}

// MARK: [RawRepresentable] type

/// Decode an array of custom RawRepresentable types with a mandatory key
public func json<T: RawRepresentable>(atKeyPath keyPath: Key, invalidItemBehaviour: InvalidItemBehaviour<T> = .remove) throws -> [T] where T.RawValue:JSONRawType {
public func json<T: RawRepresentable>(atKeyPath keyPath: Key, invalidItemBehaviour: InvalidItemBehaviour<T> = .remove) throws -> [T] where T.RawValue: JSONRawType {

return try decodeArray(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour) { keyPath, jsonArray, value in
let rawValue: T.RawValue = try getValue(atKeyPath: keyPath, array: jsonArray, value: value)

guard let value = T(rawValue:rawValue) else {
guard let value = T(rawValue: rawValue) else {
throw DecodingError(dictionary: self, keyPath: keyPath, expectedType: T.self, value: rawValue, array: jsonArray, reason: .incorrectRawRepresentableRawValue)
}
return value
}
}

/// Optionally decode an array of RawRepresentable types with a mandatory key
public func json<T: RawRepresentable>(atKeyPath keyPath: Key, invalidItemBehaviour: InvalidItemBehaviour<T> = .remove) -> [T]? where T.RawValue:JSONRawType {
return try? json(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour)
public func json<T: RawRepresentable>(atKeyPath keyPath: Key, invalidItemBehaviour: InvalidItemBehaviour<T> = .remove) -> [T]? where T.RawValue: JSONRawType {
return try? decodeArray(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour) { keyPath, jsonArray, value in
let rawValue: T.RawValue = try getValue(atKeyPath: keyPath, array: jsonArray, value: value)

guard let value = T(rawValue: rawValue) else {
throw DecodingError(dictionary: self, keyPath: keyPath, expectedType: T.self, value: rawValue, array: jsonArray, reason: .incorrectRawRepresentableRawValue)
}
return value
}
// return try? json(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour)
}

// MARK: [String: RawRepresentable] type

/// Decode a dictionary of custom RawRepresentable types with a mandatory key
public func json<T: RawRepresentable>(atKeyPath keyPath: Key, invalidItemBehaviour: InvalidItemBehaviour<T> = .remove) throws -> [String: T] where T.RawValue:JSONRawType {
public func json<T: RawRepresentable>(atKeyPath keyPath: Key, invalidItemBehaviour: InvalidItemBehaviour<T> = .remove) throws -> [String: T] where T.RawValue: JSONRawType {
return try decodeDictionary(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour) { jsonDictionary, key in
let rawValue: T.RawValue = try jsonDictionary.getValue(atKeyPath: key)

guard let value = T(rawValue:rawValue) else {
guard let value = T(rawValue: rawValue) else {
throw DecodingError(dictionary: jsonDictionary, keyPath: keyPath, expectedType: T.self, value: rawValue, reason: .incorrectRawRepresentableRawValue)
}
return value
}
}

/// Optionally decode a dictionary of RawRepresentable types with a mandatory key
public func json<T: RawRepresentable>(atKeyPath keyPath: Key, invalidItemBehaviour: InvalidItemBehaviour<T> = .remove) -> [String: T]? where T.RawValue:JSONRawType {
return try? json(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour)
public func json<T: RawRepresentable>(atKeyPath keyPath: Key, invalidItemBehaviour: InvalidItemBehaviour<T> = .remove) -> [String: T]? where T.RawValue: JSONRawType {
return try? decodeDictionary(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour) { jsonDictionary, key in
let rawValue: T.RawValue = try jsonDictionary.getValue(atKeyPath: key)

guard let value = T(rawValue: rawValue) else {
throw DecodingError(dictionary: jsonDictionary, keyPath: keyPath, expectedType: T.self, value: rawValue, reason: .incorrectRawRepresentableRawValue)
}
return value
}
// return try? json(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour)
}

// MARK: JSONPrimitiveConvertible type
Expand Down Expand Up @@ -237,7 +275,15 @@ extension Dictionary where Key: StringProtocol {

/// Optionally decode an array custom raw types with a mandatory key
public func json<T: JSONPrimitiveConvertible>(atKeyPath keyPath: Key, invalidItemBehaviour: InvalidItemBehaviour<T> = .remove) -> [T]? {
return try? json(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour)
return try? decodeArray(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour) { keyPath, jsonArray, value in
let jsonValue: T.JSONType = try getValue(atKeyPath: keyPath, array: jsonArray, value: value)

guard let transformedValue = T.from(jsonValue: jsonValue) else {
throw DecodingError(dictionary: self, keyPath: keyPath, expectedType: T.self, value: jsonValue, array: jsonArray, reason: .conversionFailure)
}
return transformedValue
}
// return try? json(atKeyPath: keyPath, invalidItemBehaviour: invalidItemBehaviour)
}

// MARK: JSONDictionary and JSONArray creation
Expand Down
2 changes: 1 addition & 1 deletion Sources/JSONUtilities/Dictionary+KeyPath.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ extension Dictionary {

keys.removeFirst()

if !keys.isEmpty, let subDictionary = value as? [Key : Any] {
if !keys.isEmpty, let subDictionary = value as? [Key: Any] {
let rejoined = keys.joined(separator: ".")
return subDictionary[keyPath: rejoined]
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/JSONUtilities/JSONFileLoading.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import Foundation

public typealias JSONDictionary = [String : Any]
public typealias JSONDictionary = [String: Any]
public typealias JSONArray = [Any]

/**
Expand Down
4 changes: 2 additions & 2 deletions Tests/JSONUtilitiesTests/Mocks/MockChild.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ struct MockChild {
let bool: Bool
}

extension MockChild : JSONObjectConvertible {
extension MockChild: JSONObjectConvertible {
init(jsonDictionary: JSONDictionary) throws {
string = try jsonDictionary.json(atKeyPath: "stringKey")
integer = try jsonDictionary.json(atKeyPath: "integerKey")
Expand All @@ -27,7 +27,7 @@ extension MockChild : JSONObjectConvertible {

// MARK: Extensions necessary for testing

extension MockChild : Equatable {}
extension MockChild: Equatable {}

func == (lhs: MockChild, rhs: MockChild) -> Bool {
return lhs.string == rhs.string &&
Expand Down

0 comments on commit 44e9ab1

Please sign in to comment.