diff --git a/EosioSwift.xcodeproj/project.pbxproj b/EosioSwift.xcodeproj/project.pbxproj index 21748664..96144329 100644 --- a/EosioSwift.xcodeproj/project.pbxproj +++ b/EosioSwift.xcodeproj/project.pbxproj @@ -25,6 +25,7 @@ 3EE762A22268C48D00D8DC33 /* EosioRpcProviderEndpointsPromises.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EE762A12268C48D00D8DC33 /* EosioRpcProviderEndpointsPromises.swift */; }; 3EE762A422690E9200D8DC33 /* RpcProviderEndpointPromiseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3EE762A322690E9200D8DC33 /* RpcProviderEndpointPromiseTests.swift */; }; 4FD31C65A4889CF91BFCE984 /* Pods_EosioSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D3E4478EE834B70DDF06A7FA /* Pods_EosioSwift.framework */; }; + 5D8C430D235F986700F3A146 /* DictionaryExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D8C430C235F986700F3A146 /* DictionaryExtensionTests.swift */; }; 6B80D26921FA6DDF00716A7B /* EosioSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6B80D25F21FA6DDF00716A7B /* EosioSwift.framework */; }; 6B80D27021FA6DDF00716A7B /* EosioSwift.h in Headers */ = {isa = PBXBuildFile; fileRef = 6B80D26221FA6DDF00716A7B /* EosioSwift.h */; settings = {ATTRIBUTES = (Public, ); }; }; 8F49E8CF225E6E6A00082631 /* RpcProviderRequestModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F49E8CE225E6E6A00082631 /* RpcProviderRequestModels.swift */; }; @@ -99,6 +100,7 @@ 3EE762A322690E9200D8DC33 /* RpcProviderEndpointPromiseTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RpcProviderEndpointPromiseTests.swift; sourceTree = ""; }; 5835070C5F7998E17BF06017 /* Pods_EosioSwiftTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_EosioSwiftTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 5ACC322368A39C81F88A1553 /* Pods-EosioSwift.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-EosioSwift.debug.xcconfig"; path = "Pods/Target Support Files/Pods-EosioSwift/Pods-EosioSwift.debug.xcconfig"; sourceTree = ""; }; + 5D8C430C235F986700F3A146 /* DictionaryExtensionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DictionaryExtensionTests.swift; sourceTree = ""; }; 6B80D25F21FA6DDF00716A7B /* EosioSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = EosioSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 6B80D26221FA6DDF00716A7B /* EosioSwift.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EosioSwift.h; sourceTree = ""; }; 6B80D26321FA6DDF00716A7B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -258,6 +260,7 @@ isa = PBXGroup; children = ( 8F6B04CA22287B1D00215CD0 /* DataExtensionsTests.swift */, + 5D8C430C235F986700F3A146 /* DictionaryExtensionTests.swift */, 8F6B04C722287B1D00215CD0 /* EncodableExtensionTests.swift */, 8F6B04CB22287B1D00215CD0 /* EosioNameTests.swift */, 8F6B04C922287B1D00215CD0 /* StringExtensionsTests.swift */, @@ -617,6 +620,7 @@ 8F6B04CE22287B1D00215CD0 /* StringExtensionsTests.swift in Sources */, BBAC7BCE225266A40035CDBC /* DateExtensionTests.swift in Sources */, 8F77127D2232FD6D004256D3 /* EosioTransactionTests.swift in Sources */, + 5D8C430D235F986700F3A146 /* DictionaryExtensionTests.swift in Sources */, 1F9DCB7A22569A2600853105 /* EosioRpcProviderTests.swift in Sources */, B4E8F6C222320EB700FA7E63 /* RIPEMD160Tests.swift in Sources */, 8F6B04CF22287B1D00215CD0 /* DataExtensionsTests.swift in Sources */, diff --git a/EosioSwift/Extensions/DictionaryExtensions.swift b/EosioSwift/Extensions/DictionaryExtensions.swift index 44bbd321..8f75e78a 100644 --- a/EosioSwift/Extensions/DictionaryExtensions.swift +++ b/EosioSwift/Extensions/DictionaryExtensions.swift @@ -12,7 +12,8 @@ public extension Dictionary { /// Returns a JSON string representation of the dictionary or nil if the dictionary can't be encoded to a JSON string. var jsonString: String? { - guard let jsonData = try? JSONSerialization.data(withJSONObject: self, options: [.sortedKeys]) else { return nil } + guard JSONSerialization.isValidJSONObject(self), + let jsonData = try? JSONSerialization.data(withJSONObject: self, options: [.sortedKeys]) else { return nil } return String(data: jsonData, encoding: .utf8) } diff --git a/EosioSwiftTests/DictionaryExtensionTests.swift b/EosioSwiftTests/DictionaryExtensionTests.swift new file mode 100644 index 00000000..75e3d397 --- /dev/null +++ b/EosioSwiftTests/DictionaryExtensionTests.swift @@ -0,0 +1,39 @@ +// +// DictionaryExtensionTests.swift +// EosioSwiftTests + +// Created by Paul Kim on 10/22/19 +// Copyright (c) 2017-2019 block.one and its contributors. All rights reserved. +// + +import XCTest + +class DictionaryExtensionTests: XCTestCase { + + func testJsonStringWithValidDictionaryReturnsCorrectJsonString() { + let dict: [String: Any?] = ["string": "string", + "integer": 1, + "nil": nil, + "array": ["a", "b", "c"], + "dict": ["key": "value"]] + let expectedJsonString = "{\"array\":[\"a\",\"b\",\"c\"],\"dict\":{\"key\":\"value\"},\"integer\":1,\"nil\":null,\"string\":\"string\"}" + + guard let resultingJsonString = dict.jsonString else { + return XCTFail("jsonString on valid dictionary returns nil.") + } + XCTAssertEqual(resultingJsonString, expectedJsonString) + } + + func testJsonStringWithInvalidDictionaryReturnsNil() { + let dict: [String: Any?] = ["string": "string", + "integer": 1, + "nil": nil, + "array": ["a", "b", "c"], + "dict": ["key": "value"], + "enum": Calendar.Identifier.gregorian] + + let resultingJsonString = dict.jsonString + XCTAssertNil(resultingJsonString, "jsonString on invalid dictionary returns non-nil.") + } + +}