我想在我的swift项目中创建一个函数,将字符串转换为字典json格式,但我得到了一个错误:

不能转换表达式的类型(@lvalue NSData,选项:IntegerLitralConvertible…

这是我的代码:

func convertStringToDictionary (text:String) -> Dictionary<String,String> {

    var data :NSData = text.dataUsingEncoding(NSUTF8StringEncoding)!
    var json :Dictionary = NSJSONSerialization.JSONObjectWithData(data, options:0, error: nil)
    return json
} 

我在Objective-C中创建了这个函数:

- (NSDictionary*)convertStringToDictionary:(NSString*)string {
  NSError* error;
  //giving error as it takes dic, array,etc only. not custom object.
  NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
  id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
  return json;
}

当前回答

在Swift 3中,JSONSerialization有一个叫做json Object的方法(With: options:)。json对象(带:options:)有以下声明:

class func jsonObject(with data: Data, options opt: JSONSerialization.ReadingOptions = []) throws -> Any

从给定的JSON数据返回一个Foundation对象。

当你使用json Object(with: options:)时,你必须处理错误处理(try, try?或者试试!)和类型转换(来自Any)。因此,您可以使用以下模式之一来解决问题。


# 1。使用抛出并返回非可选类型的方法

import Foundation

func convertToDictionary(from text: String) throws -> [String: String] {
    guard let data = text.data(using: .utf8) else { return [:] }
    let anyResult: Any = try JSONSerialization.jsonObject(with: data, options: [])
    return anyResult as? [String: String] ?? [:]
}

用法:

let string1 = "{\"City\":\"Paris\"}"
do {
    let dictionary = try convertToDictionary(from: string1)
    print(dictionary) // prints: ["City": "Paris"]
} catch {
    print(error)
}
let string2 = "{\"Quantity\":100}"
do {
    let dictionary = try convertToDictionary(from: string2)
    print(dictionary) // prints [:]
} catch {
    print(error)
}
let string3 = "{\"Object\"}"
do {
    let dictionary = try convertToDictionary(from: string3)
    print(dictionary)
} catch {
    print(error) // prints: Error Domain=NSCocoaErrorDomain Code=3840 "No value for key in object around character 9." UserInfo={NSDebugDescription=No value for key in object around character 9.}
}

# 2。使用抛出并返回可选类型的方法

import Foundation

func convertToDictionary(from text: String) throws -> [String: String]? {
    guard let data = text.data(using: .utf8) else { return [:] }
    let anyResult: Any = try JSONSerialization.jsonObject(with: data, options: [])
    return anyResult as? [String: String]
}

用法:

let string1 = "{\"City\":\"Paris\"}"
do {
    let dictionary = try convertToDictionary(from: string1)
    print(String(describing: dictionary)) // prints: Optional(["City": "Paris"])
} catch {
    print(error)
}
let string2 = "{\"Quantity\":100}"
do {
    let dictionary = try convertToDictionary(from: string2)
    print(String(describing: dictionary)) // prints nil
} catch {
    print(error)
}
let string3 = "{\"Object\"}"
do {
    let dictionary = try convertToDictionary(from: string3)
    print(String(describing: dictionary))
} catch {
    print(error) // prints: Error Domain=NSCocoaErrorDomain Code=3840 "No value for key in object around character 9." UserInfo={NSDebugDescription=No value for key in object around character 9.}
}

# 3。使用不抛出并返回非可选类型的方法

import Foundation

func convertToDictionary(from text: String) -> [String: String] {
    guard let data = text.data(using: .utf8) else { return [:] }
    let anyResult: Any? = try? JSONSerialization.jsonObject(with: data, options: [])
    return anyResult as? [String: String] ?? [:]
}

用法:

let string1 = "{\"City\":\"Paris\"}"
let dictionary1 = convertToDictionary(from: string1)
print(dictionary1) // prints: ["City": "Paris"]
let string2 = "{\"Quantity\":100}"
let dictionary2 = convertToDictionary(from: string2)
print(dictionary2) // prints: [:]
let string3 = "{\"Object\"}"
let dictionary3 = convertToDictionary(from: string3)
print(dictionary3) // prints: [:]

# 4。使用不抛出并返回可选类型的方法

import Foundation

func convertToDictionary(from text: String) -> [String: String]? {
    guard let data = text.data(using: .utf8) else { return nil }
    let anyResult = try? JSONSerialization.jsonObject(with: data, options: [])
    return anyResult as? [String: String]
}

用法:

let string1 = "{\"City\":\"Paris\"}"
let dictionary1 = convertToDictionary(from: string1)
print(String(describing: dictionary1)) // prints: Optional(["City": "Paris"])
let string2 = "{\"Quantity\":100}"
let dictionary2 = convertToDictionary(from: string2)
print(String(describing: dictionary2)) // prints: nil
let string3 = "{\"Object\"}"
let dictionary3 = convertToDictionary(from: string3)
print(String(describing: dictionary3)) // prints: nil

其他回答

我发现代码转换json字符串到NSDictionary或NSArray。只需添加扩展。

斯威夫特3.0

如何使用

let jsonData = (convertedJsonString as! String).parseJSONString

扩展

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
    }
}

}

斯威夫特5

extension String {
    func convertToDictionary() -> [String: Any]? {
        if let data = data(using: .utf8) {
            return try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
        }
        return nil
    }
}

斯威夫特4

extension String {
    func convertToDictionary() -> [String: Any]? {
        if let data = self.data(using: .utf8) {
            do {
                return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
            } catch {
                print(error.localizedDescription)
            }
        }
        return nil
    }
}

细节

Xcode版本10.3 (10G8), Swift 5

解决方案

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)
    }
}

使用

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)

检测样本

不要忘记在这里粘贴解决方案代码

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)")
}

测试日志

//////////////////////////////////////////
-- 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.}

斯威夫特3:

if let data = text.data(using: String.Encoding.utf8) {
    do {
        let json = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String:Any]
        print(json)
    } catch {
        print("Something went wrong")
    }
}