How to convert a JSON string to a dictionary?

前端 未结 10 917
情深已故
情深已故 2020-11-22 05:57

I want to make one function in my swift project that converts String to Dictionary json format but I got one error:

Cannot convert expression\'s type

相关标签:
10条回答
  • 2020-11-22 06:57
    let JSONData = jsonString.data(using: .utf8)!
    
    let jsonResult = try JSONSerialization.jsonObject(with: data, options: .mutableLeaves)
    
    guard let userDictionary = jsonResult as? Dictionary<String, AnyObject> else {
                throw NSError()}
    
    0 讨论(0)
  • 2020-11-22 06:59

    I found code which converts the json string to NSDictionary or NSArray. Just add the extension.

    SWIFT 3.0

    HOW TO USE

    let jsonData = (convertedJsonString as! String).parseJSONString
    

    EXTENSION

    extension String
    {
    var parseJSONString: AnyObject?
    {
        let data = self.data(using: String.Encoding.utf8, allowLossyConversion: false)
        if let jsonData = data
        {
            // Will return an object or nil if JSON decoding fails
            do
            {
                let message = try JSONSerialization.jsonObject(with: jsonData, options:.mutableContainers)
                if let jsonResult = message as? NSMutableArray {
                    return jsonResult //Will return the json array output
                } else if let jsonResult = message as? NSMutableDictionary {
                    return jsonResult //Will return the json dictionary output
                } else {
                    return nil
                }
            }
            catch let error as NSError
            {
                print("An error occurred: \(error)")
                return nil
            }
        }
        else
        {
            // Lossless conversion of the string was not possible
            return nil
        }
    }
    

    }

    0 讨论(0)
  • 2020-11-22 07:00

    for swift 5, I write a demo to verify it.

    extension String {
    
        /// convert JsonString to Dictionary
        func convertJsonStringToDictionary() -> [String: Any]? {
            if let data = data(using: .utf8) {
                return (try? JSONSerialization.jsonObject(with: data, options: [])) as? [String: Any]
            }
    
            return nil
        }
    }
    
    let str = "{\"name\":\"zgpeace\"}"
    let dict = str.convertJsonStringToDictionary()
    print("string > \(str)")  
    // string > {"name":"zgpeace"}
    print("dicionary > \(String(describing: dict))") 
    // dicionary > Optional(["name": zgpeace])
    
    0 讨论(0)
  • 2020-11-22 07:02

    Details

    • Xcode Version 10.3 (10G8), Swift 5

    Solution

    import Foundation
    
    // MARK: - CastingError
    
    struct CastingError: Error {
        let fromType: Any.Type
        let toType: Any.Type
        init<FromType, ToType>(fromType: FromType.Type, toType: ToType.Type) {
            self.fromType = fromType
            self.toType = toType
        }
    }
    
    extension CastingError: LocalizedError {
        var localizedDescription: String { return "Can not cast from \(fromType) to \(toType)" }
    }
    
    extension CastingError: CustomStringConvertible { var description: String { return localizedDescription } }
    
    // MARK: - Data cast extensions
    
    extension Data {
        func toDictionary(options: JSONSerialization.ReadingOptions = []) throws -> [String: Any] {
            return try to(type: [String: Any].self, options: options)
        }
    
        func to<T>(type: T.Type, options: JSONSerialization.ReadingOptions = []) throws -> T {
            guard let result = try JSONSerialization.jsonObject(with: self, options: options) as? T else {
                throw CastingError(fromType: type, toType: T.self)
            }
            return result
        }
    }
    
    // MARK: - String cast extensions
    
    extension String {
        func asJSON<T>(to type: T.Type, using encoding: String.Encoding = .utf8) throws -> T {
            guard let data = data(using: encoding) else { throw CastingError(fromType: type, toType: T.self) }
            return try data.to(type: T.self)
        }
    
        func asJSONToDictionary(using encoding: String.Encoding = .utf8) throws -> [String: Any] {
            return try asJSON(to: [String: Any].self, using: encoding)
        }
    }
    
    // MARK: - Dictionary cast extensions
    
    extension Dictionary {
        func toData(options: JSONSerialization.WritingOptions = []) throws -> Data {
            return try JSONSerialization.data(withJSONObject: self, options: options)
        }
    }
    

    Usage

    let value1 = try? data.toDictionary()
    let value2 = try? data.to(type: [String: Any].self)
    let value3 = try? data.to(type: [String: String].self)
    let value4 = try? string.asJSONToDictionary()
    let value5 = try? string.asJSON(to: [String: String].self)
    

    Test sample

    Do not forget to paste the solution code here

    func testDescriber(text: String, value: Any) {
        print("\n//////////////////////////////////////////")
        print("-- \(text)\n\n  type: \(type(of: value))\n  value: \(value)")
    }
    
    let json1: [String: Any] = ["key1" : 1, "key2": true, "key3" : ["a": 1, "b": 2], "key4": [1,2,3]]
    var jsonData = try? json1.toData()
    testDescriber(text: "Sample test of func toDictionary()", value: json1)
    if let data = jsonData {
        print("  Result: \(String(describing: try? data.toDictionary()))")
    }
    
    testDescriber(text: "Sample test of func to<T>() -> [String: Any]", value: json1)
    if let data = jsonData {
        print("  Result: \(String(describing: try? data.to(type: [String: Any].self)))")
    }
    
    testDescriber(text: "Sample test of func to<T>() -> [String] with cast error", value: json1)
    if let data = jsonData {
        do {
            print("  Result: \(String(describing: try data.to(type: [String].self)))")
        } catch {
            print("  ERROR: \(error)")
        }
    }
    
    let array = [1,4,5,6]
    testDescriber(text: "Sample test of func to<T>() -> [Int]", value: array)
    if let data = try? JSONSerialization.data(withJSONObject: array) {
        print("  Result: \(String(describing: try? data.to(type: [Int].self)))")
    }
    
    let json2 = ["key1": "a", "key2": "b"]
    testDescriber(text: "Sample test of func to<T>() -> [String: String]", value: json2)
    if let data = try? JSONSerialization.data(withJSONObject: json2) {
        print("  Result: \(String(describing: try? data.to(type: [String: String].self)))")
    }
    
    let jsonString = "{\"key1\": \"a\", \"key2\": \"b\"}"
    testDescriber(text: "Sample test of func to<T>() -> [String: String]", value: jsonString)
    print("  Result: \(String(describing: try? jsonString.asJSON(to: [String: String].self)))")
    
    testDescriber(text: "Sample test of func to<T>() -> [String: String]", value: jsonString)
    print("  Result: \(String(describing: try? jsonString.asJSONToDictionary()))")
    
    let wrongJsonString = "{\"key1\": \"a\", \"key2\":}"
    testDescriber(text: "Sample test of func to<T>() -> [String: String] with JSONSerialization error", value: jsonString)
    do {
        let json = try wrongJsonString.asJSON(to: [String: String].self)
        print("  Result: \(String(describing: json))")
    } catch {
        print("  ERROR: \(error)")
    }
    

    Test log

    //////////////////////////////////////////
    -- Sample test of func toDictionary()
    
      type: Dictionary<String, Any>
      value: ["key4": [1, 2, 3], "key2": true, "key3": ["a": 1, "b": 2], "key1": 1]
      Result: Optional(["key4": <__NSArrayI 0x600002a35380>(
    1,
    2,
    3
    )
    , "key2": 1, "key3": {
        a = 1;
        b = 2;
    }, "key1": 1])
    
    //////////////////////////////////////////
    -- Sample test of func to<T>() -> [String: Any]
    
      type: Dictionary<String, Any>
      value: ["key4": [1, 2, 3], "key2": true, "key3": ["a": 1, "b": 2], "key1": 1]
      Result: Optional(["key4": <__NSArrayI 0x600002a254d0>(
    1,
    2,
    3
    )
    , "key2": 1, "key1": 1, "key3": {
        a = 1;
        b = 2;
    }])
    
    //////////////////////////////////////////
    -- Sample test of func to<T>() -> [String] with cast error
    
      type: Dictionary<String, Any>
      value: ["key4": [1, 2, 3], "key2": true, "key3": ["a": 1, "b": 2], "key1": 1]
      ERROR: Can not cast from Array<String> to Array<String>
    
    //////////////////////////////////////////
    -- Sample test of func to<T>() -> [Int]
    
      type: Array<Int>
      value: [1, 4, 5, 6]
      Result: Optional([1, 4, 5, 6])
    
    //////////////////////////////////////////
    -- Sample test of func to<T>() -> [String: String]
    
      type: Dictionary<String, String>
      value: ["key1": "a", "key2": "b"]
      Result: Optional(["key1": "a", "key2": "b"])
    
    //////////////////////////////////////////
    -- Sample test of func to<T>() -> [String: String]
    
      type: String
      value: {"key1": "a", "key2": "b"}
      Result: Optional(["key1": "a", "key2": "b"])
    
    //////////////////////////////////////////
    -- Sample test of func to<T>() -> [String: String]
    
      type: String
      value: {"key1": "a", "key2": "b"}
      Result: Optional(["key1": a, "key2": b])
    
    //////////////////////////////////////////
    -- Sample test of func to<T>() -> [String: String] with JSONSerialization error
    
      type: String
      value: {"key1": "a", "key2": "b"}
      ERROR: Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 21." UserInfo={NSDebugDescription=Invalid value around character 21.}
    
    0 讨论(0)
提交回复
热议问题