使用大引号时,将字符串 JSON 转换为 Swift 中的字典

Posted

技术标签:

【中文标题】使用大引号时,将字符串 JSON 转换为 Swift 中的字典【英文标题】:Convert a string JSON to a dictionary in Swift when curly quotes are used 【发布时间】:2020-01-24 19:18:31 【问题描述】:

我有一个字符串 JSON,但它有花哨的大引号导致 NSJSONSerialization 失败。

let str = "“title”:\"this is a “test” example\""

try! JSONSerialization.jsonObject(with: str.data(using: .utf8)!) // Error

title 周围的引号是双引号,显然 JSONSerialization 无法处理它并失败。一种天真的方法是简单地用非卷引号替换所有卷引号实例。这种方法的问题在于它会改变 test 周围的花括号,而这不应该被改变! title 周围的引号可以更改,但test 周围的引号不应该。

我可以做些什么来解决这个问题?

【问题讨论】:

" 更改为" 更改为\" 更改为" ? 【参考方案1】:

要解决此问题,您与创建该字符串的人交谈,该字符串目前 包含 JSON,并说服他们创建一个 确实 包含 JSON 的字符串。

对于 JSON,规则是:如果您的解析器无法解析它,那么它就坏了,您不要碰它。

问题不在于 JSONSerialization 无法处理它。问题是 JSONSerialization 在任何情况下都绝对不得处理它。因为它不是 JSON。

【讨论】:

【参考方案2】:

如果大引号仅用于键,则此正则表达式将完成这项工作:

let str = "“title”:\"this is a “test” example\""

let strFixed = str.replacingOccurrences(
    of: #"“(.[^”]*)”:\"(.[^\"]*)\""#,
    with: "\"$1\":\"$2\"",
    options: .regularExpression
)

// It's strongly recommended to use try/catch instead of force unwrapping.
let json = try! JSONSerialization.jsonObject(with: strFixed.data(using: .utf8)!)

如果我们打印json,我们会得到正确的结果:


    title = "this is a \U201ctest\U201d example";


说明

“(.[^”]*)”:\"(.[^\"]*)\" ---------------------- “(.[^”]*)” 匹配大括号之间的所有内容, 除了右花括号字符 : 键和值之间的分隔符 \"(.[^\"]*)\" 匹配双引号之间的所有内容, 除了双引号字符 \"$1\":\"$2\" ------------- \"$1\" 将第一个捕获的组放在双引号之间 : 键和值之间的分隔符 \"$2\" 将第二个捕获的组放在双引号之间

【讨论】:

以上是关于使用大引号时,将字符串 JSON 转换为 Swift 中的字典的主要内容,如果未能解决你的问题,请参考以下文章

如何将带单引号的字符串转换为双引号以进行 json 解析

AFNetworking 在格式化 JSON 时将我的双打转换为带引号的字符串

python模块-jsonpickle

当字符串在双引号内有单引号时,如何在Javascript中将此字符串转换为JSON对象

Python如何将单引号转换为双引号以格式化为json字符串

如何格式化json数组