Swift: преобразовать структуру в JSON?

Я создал struct и хочу сохранить его как JSON файл.

struct Sentence {
    var sentence = ""
    var lang = ""
}

var s = Sentence()
s.sentence = "Hello world"
s.lang = "en"
print(s)

..., что приводит к:

Sentence(sentence: "Hello world", lang: "en")

Но как я могу преобразовать объект struct в нечто вроде:

{
    "sentence": "Hello world",
    "lang": "en"
}

Ответ 1

Вы можете добавить вычисляемое свойство, чтобы получить представление JSON, и статическую функцию (класс) для создания массива JSON из массива Sentence.

struct Sentence {
  var sentence = ""
  var lang = ""

  static func jsonArray(array : [Sentence]) -> String
  {
    return "[" + array.map {$0.jsonRepresentation}.joinWithSeparator(",") + "]"
  }

  var jsonRepresentation : String {
    return "{\"sentence\":\"\(sentence)\",\"lang\":\"\(lang)\"}"
  }
}


let sentences = [Sentence(sentence: "Hello world", lang: "en"), Sentence(sentence: "Hallo Welt", lang: "de")]
let jsonArray = Sentence.jsonArray(sentences)
print(jsonArray) // [{"sentence":"Hello world","lang":"en"},{"sentence":"Hallo Welt","lang":"de"}]

Редактировать:

Swift 4 представляет протокол Codable, который предоставляет очень удобный способ кодирования и декодирования пользовательских структур.

struct Sentence : Codable {
    let sentence : String
    let lang : String
}

let sentences = [Sentence(sentence: "Hello world", lang: "en"), 
                 Sentence(sentence: "Hallo Welt", lang: "de")]

do {
    let jsonData = try JSONEncoder().encode(sentences)
    let jsonString = String(data: jsonData, encoding: .utf8)!
    print(jsonString) // [{"sentence":"Hello world","lang":"en"},{"sentence":"Hallo Welt","lang":"de"}]

    // and decode it back
    let decodedSentences = try JSONDecoder().decode([Sentence].self, from: jsonData)
    print(decodedSentences)
} catch { print(error) }

Ответ 2

Используйте класс NSJSONSerialization.

Используя эту ссылку для , вам может понадобиться создать функцию, которая возвращает сериализованную строку JSON. В этой функции вы можете взять необходимые свойства и создать из них NSDictionary и использовать класс, упомянутый выше.

Что-то вроде этого:

struct Sentence {
    var sentence = ""
    var lang = ""

    func toJSON() -> String? {
        let props = ["Sentence": self.sentence, "lang": lang]
        do {
            let jsonData = try NSJSONSerialization.dataWithJSONObject(props,
            options: .PrettyPrinted)
            return String(data: jsonData, encoding: NSUTF8StringEncoding)
        } catch let error {
            print("error converting to json: \(error)")
            return nil
        }
    }

}

Поскольку ваша структура имеет только два свойства, может быть проще просто создать строку JSON самостоятельно.

Ответ 3

Swift 4 поддерживает протокол Encodable, например

struct Sentence: Encodable {
    var sentence: String?
    var lang: String?
}

let sentence = Sentence(sentence: "Hello world", lang: "en")

Теперь вы можете автоматически конвертировать ваш Struct в JSON с помощью JSONEncoder:

let jsonEncoder = JSONEncoder()
let jsonData = try jsonEncoder.encode(sentence)

Распечатай:

let jsonString = String(data: jsonData, encoding: .utf8)
print(jsonString)

{
    "sentence": "Hello world",
    "lang": "en"
}

https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types