Протокол быстрого кодирования. Проблема с кодировкой строк

Недавно я столкнулся с проблемой при кодировании объекта, который соответствует протоколу Codable.

Вот код для игровой площадки:

class Person: Codable {
    var name: String?
    var age: Int?
    var isDev: Bool?
}

let p1 = Person()
p1.name = "John N."
p1.age = 13
p1.isDev = false

let p2 = Person()
p2.name = "Jack"
p2.age = 19
p2.isDev = true

let people = [p1, p2]
let data = try JSONEncoder().encode(people)
let j = try! JSONSerialization.jsonObject(with: data, options: [])

print(j)

Это вывод, который я получаю в консоли Playground:

введите здесь описание изображения

Как видите, закодированное имя p1 заключено в кавычки, а имя p2 — нет. Итак, мой вопрос: почему?

P.S. Единственное, что я заметил, это добавление, например. символ пробела или подчеркивания в любом месте при установке строкового значения добавляет кавычки в json. p1.name содержит пробел, поэтому он закодирован правильно.

Любые мысли приветствуются.


person Gasper J.    schedule 14.01.2021    source источник
comment
Вы печатаете объект словаря. Это не имеет ничего общего с JSON или кодировкой, а только с тем, как объекты выводятся на консоль. Строки с пробелом заключаются в кавычки, строки без пробела не заключаются в кавычки.   -  person Sulthan    schedule 14.01.2021
comment
Именно так это печатается, когда значение содержит пробел, вам не нужно об этом беспокоиться   -  person Claus Jørgensen    schedule 14.01.2021
comment
спасибо, ребята, за ваше объяснение. Я отправил закодированный объект в одну из конечных точек приложения, он работает правильно, несмотря на то, что он печатался так в Playground.   -  person Gasper J.    schedule 14.01.2021


Ответы (2)


j — это десериализованный объект JSON, а не строка JSON (закодированные данные). Если вы хотите увидеть JSON, преобразуйте data в строку, так как это и есть JSON:

print(String(data: data, encoding: .utf8)!)

j на самом деле является представлением ваших данных JSON с использованием NSArrays и NSDictionarys. Оказывается, если вы напечатаете NSDictionary со строками в них, кавычки будут добавлены к строкам, содержащим пробелы и/или другие специальные символы, чтобы сообщить вам, где на самом деле начинается и заканчивается строка.

Сравнивать:

print(["name": "hello"] as NSDictionary)
print(["name": "hello world"] as NSDictionary)
print(["hello"] as NSArray)
print(["hello world"] as NSArray)

Выход:

{
    name = hello;
}
{
    name = "hello world";
}
(
    hello
)
(
    "hello world"
)
person Sweeper    schedule 14.01.2021

Этот ответ не будет решать реальный вопрос, но я считаю, что это то, чего хочет достичь автор вопроса. В опубликованном фрагменте кода вы фактически печатаете словарь, а не строку JSON. Вы делаете следующие вещи:

  1. Преобразуйте объект Person в данные JSON.
  2. Преобразуйте данные JSON в Dictionary
  3. Распечатать словарь

Напомним, что данные JSON на самом деле представляют собой байтовое представление строки JSON.

Вы можете проверить строку JSON, просто сделав это:

class Person: Codable {
    var name: String?
    var age: Int?
    var isDev: Bool?
}

let p1 = Person()
p1.name = "John N."
p1.age = 13
p1.isDev = false

let p2 = Person()
p2.name = "Jack"
p2.age = 19
p2.isDev = true

let people = [p1, p2]
let data = try JSONEncoder().encode(people)
let jsonString = String(data: data, encoding: .utf8)

print(jsonString ?? "invalid JSON data")
person Vlad Rusu    schedule 14.01.2021