将Swift中的JSON字符串解析为字典

时间:2018-04-23 08:59:10

标签: json swift dictionary osc

这可能非常简单,但我不熟悉使用JSON。

我从OSC消息的参数中收到此JSON字符串:

{"status":"ok","address":"\/workspaces","data":[{"version":"4.2.1","displayName":"Untitled Workspace","uniqueID":"82688E14-5E8F-428E-A781-8ABC920A5515","hasPasscode":false}]}

我正在尝试将其转换为字典,因此我可以处理数据。我在Stack Overflow上尝试了很多答案,但this one似乎最相关。但是,它会抛出错误“数据无法读取,因为它的格式不正确。”

有人可以告知为什么这个字符串的格式错误吗?

这是我的代码:

    func didReceive(_ message: OSCMessage){

    let jsonString = String(describing: message.arguments[0]!)

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

    let dict = convertToDictionary(text: jsonString)
    print(dict as Any)

}

非常感谢!

编辑:我修改了代码以删除可能导致错误的“\”。但是,它仍然会使用以下代码抛出相同的错误:

    func didReceive(_ message: OSCMessage){

    let jsonString = message.arguments[0] as! String
    let jsonStringEdit = jsonString.replacingOccurrences(of: "\\", with: "")

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

    let dict = convertToDictionary(text: jsonStringEdit)
    print(dict as Any)

}

编辑2:

解决!

字符串末尾似乎有某种null / non-printable字符。我现在通过在解析之前删除它来解决了这个问题。我已使用此代码将其删除:

jsonString.remove(at: jsonString.index(before: jsonString.endIndex))

感谢大家的建议!

3 个答案:

答案 0 :(得分:0)

JSON响应似乎是正确的形式:

enter image description here

我猜问题是在字符串转换中,尝试使用

--pending-merges

答案 1 :(得分:0)

这有效:

let jsonStr = """
{
    "status":"ok",
    "address":"\\/workspaces",
    "data":[{
        "version":"4.2.1",
        "displayName":"Untitled Workspace",
        "uniqueID":"82688E14-5E8F-428E-A781-8ABC920A5515",
        "hasPasscode":false
     }]
}
"""

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

let dict = convertToDictionary(text: jsonStr)
print(dict as Any)

我必须在地址值中添加一个额外的反斜杠转义字符,以便在操场上工作。这可能会导致您的问题。

答案 2 :(得分:0)

因为如果从服务接收字符串,字符串应该是可解析的。但是,如果您尝试将其用作代码而不进一步转义,则会混淆Swift解析器。但是,因为使用[String:Any]是如此令人难以置信的混乱(更不用说unSwifty :-)我建议你自己帮忙并尝试Codable协议。这样你可能会在游乐场结束这样的事情:

import Cocoa

let jsonData = """
{"status":"ok","address":"\\/workspaces","data":[{"version":"4.2.1", "displayName":"Untitled Workspace","uniqueID":"82688E14-5E8F-428E-A781-8ABC920A5515","hasPasscode":false}]}
""".data(using: .utf8)!

struct InnerData : Codable {
    let version: String
    let displayName: String
    let uniqueID: String
    let hasPasscode: Bool
}

struct AddressData : Codable {
    let status: String
    let address: String
    let data: [InnerData]
}

do {
    let adrData = try JSONDecoder().decode(AddressData.self, from:jsonData)
    print(adrData)
} catch {
    print(error)
}

完美解析(给定转义的\)并且在此之后将更好地处理。请注意,如果从某个服务获取字符串(包括\),则不需要转义。如果仍然无效,请发布错误消息(以及它出现的确切行)。

评论后更新

我刚把它添加到我的游乐场:

let jsonData2 = """
{"status":"ok","address":"/workspaces","data":[{"version":"4.2.1","displayName":"Untitled Workspace 1","uniqueID":"FE329024-DC98-4197-9B3F-2509851A1E50","hasPasscode":false}]}
""".data(using: .utf8)!

do {
    let adr = try JSONDecoder().decode(AddressData.self, from:jsonData2)
    print(adr.data[0].uniqueID)
} catch {
    print(error)
}

因此,您提供的String完美解析,但 String似乎包含一些Garbage at end.,如错误消息所示。您可能会尝试迭代其最终字符并打印出他们的代码点,如果您给出的代码首先是ASCII,ISO-8859-1或其他一些编码,这可能很容易指出一些编码问题。不幸的是推测这些东西,但它们可能很难转换成StackOverflow格式,因为我们在这里都是Unicode。在其他编码中重新解释Strings可能会导致任何数量的奇怪行为,但对我来说,它通常会在立即生成String时失败并显示错误。

从定义中访问InnerData结构只是简单明了。由于您的data标记包含Array InnerData,因此您必须在访问其内部属性之前对其进行下标,如上所述。除此之外,它不会更自然。