Конвертировать строку JSON в словарь в Swift при использовании фигурных кавычек - PullRequest
1 голос
/ 24 января 2020

У меня есть строка JSON, но в ней есть причудливые фигурные кавычки, которые приводят к сбою NSJSONSerialization.

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

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

Кавычки вокруг title являются вьющимися двойными кавычками, и, очевидно, JSONSerialization не может их обработать и терпит неудачу. Наивным подходом было бы просто заменить все вьющиеся кавычки не кудрявыми. Проблема с этим подходом состоит в том, что он изменит фигурные кавычки вокруг test, которые не должны быть изменены! Кавычки вокруг title можно менять, а к test не следует.

Что можно сделать, чтобы обойти эту проблему?

Ответы [ 2 ]

2 голосов
/ 25 января 2020

Чтобы исправить это, вы говорите с тем, кто создал строку, которая не содержит JSON на данный момент, и убеждает их создать строку, которая содержит содержит JSON.

Для JSON правило таково: если ваш синтаксический анализатор не может его проанализировать, значит, он сломан, и вы его не трогаете.

Проблема не в том, что JSONSerialization не может справиться с этим. Проблема в том, что JSONSerialization абсолютно не должна ни при каких обстоятельствах справляться с этим. Потому что это не JSON.

0 голосов
/ 25 января 2020

Если фигурные кавычки используются только для ключей, это регулярное выражение выполнит свою работу:

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

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

let json = try! JSONSerialization.jsonObject(with: strFixed.data(using: .utf8)!)

Если мы напечатаем json, мы получим правильный результат:

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

Объяснение

“(.[^”]*)”:\"(.[^\"]*)\"
------------------------
“(.[^”]*)”                match everything between curly braces,
                          except the closing curling brace character

          :               separator between keys and values

           \"(.[^\"]*)\"  match everything between double quotes,
                          except the double quote character
    \"$1\":\"$2\"
    -------------
    \"$1\"         place the first captured group between double quotes

          :        separator between keys and values

           \"$2\"  place the second captured group between double quotes
...