Как я могу читать / записывать массив объектов из / в JSON, используя класс Swift, соответствующий JSON из компонента NewtonSoft (JSON.Net)? - PullRequest
0 голосов
/ 28 января 2019

Я пытаюсь прочитать файл JSON, созданный мной с помощью анализатора NewtonSoft JSON.Net в другой (Windows) программе.JSON был создан компонентом JSON.Net при сериализации массива объектов.Пример JSON выглядит следующим образом (для этого примера я просто показываю два объекта):

[{"MaxLength":23,"HasSpecialChars":false,"HasUpperCase":true,"Key":"firstOne"},
{"MaxLength":0,"HasSpecialChars":false,"HasUpperCase":false,"Key":"secondOne"}]

Обратите внимание, что это массив объектов в json.

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

Что я пробовал

Я нашел эту запись SO: Чтение в файле JSON с использованием Swift Однако, чтобы получить массив объектов, эта запись использует отдельные структуры, которые можно кодировать следующим образом:

struct ResponseData: Decodable {
    var thisNameShowsUpInJson: [SiteKey]
}

Это заставляет внешний массивесть собственное имя свойства в JSON.

Например, единственный код, работающий в этом посте, работает только в том случае, если мой JSON изменен и включает внешний объект с именем (SiteKey), например:

 {"thisNameShowsUpInJson": [{"MaxLength":23,"HasSpecialChars":false,"HasUpperCase":true,"Key":"firstOne"},
   {"MaxLength":0,"HasSpecialChars":false,"HasUpperCase":false,"Key":"secondOne"}]
}

Однакоэто не правильно для способа, которым JSON.Net записывает массив объектов в файл.

Вот мой простой класс Swift, который я хочу сериализовать и десериализовать:

class SiteKey : Codable{
    var Key : String
    var MaxLength : Int
    var HasSpecialChars : Bool
    var HasUpperCase : Bool

    init(key : String, maxLength : Int,
         hasSpecialChars : Bool,
         hasUpperCase : Bool){
        Key = key;
        MaxLength = maxLength;
        HasSpecialChars = hasSpecialChars;
        HasUpperCase = hasUpperCase;
    } 
}

Я хотел бы прочитать данные из именованного файла и десериализовать данные в объекты.Затем я хотел бы сериализовать объекты в памяти обратно в файл, как в моем примере.

Ответы [ 2 ]

0 голосов
/ 28 января 2019

Я обнаружил код, который мне нужно использовать в Swift, который позволяет мне читать и записывать JSON (массив объектов), который выводится JSON.Net.

Я добавил два метода в свой SiteKeyobject:

func loadJson(filename fileName: String) -> [SiteKey]
func writeJson(filename fileName: String, allSiteKeys : [SiteKey])

Первая функция принимает строку, которая указывает на файл json, и возвращает массив SiteKeys, который находится в файле.Вторая функция берет имя файла и массив объектов SiteKey и записывает их в файл.

Вот измененный класс SiteKey с добавленными функциями.

class SiteKey : Codable{
    var Key : String
    var MaxLength : Int
    var HasSpecialChars : Bool
    var HasUpperCase : Bool

    init(key : String, maxLength : Int,
         hasSpecialChars : Bool,
         hasUpperCase : Bool){
        Key = key;
        MaxLength = maxLength;
        HasSpecialChars = hasSpecialChars;
        HasUpperCase = hasUpperCase;
    }

    func loadJson(filename fileName: String) -> [SiteKey]? {
        if let url = Bundle.main.url(forAuxiliaryExecutable: fileName) {
            do {
                let data = try Data(contentsOf: url)
                let decoder = JSONDecoder()
                let allKeys = try decoder.decode([SiteKey].self, from: data)
                return allKeys
            } catch {
                print("error:\(error)")
            }
        }
        return nil
    }

    func writeJson(filename fileName: String, allSiteKeys : [SiteKey]){
        let Data = try? JSONEncoder().encode(allSiteKeys)

            let pathAsURL = URL(fileURLWithPath: fileName)
            do {
                try Data?.write(to: pathAsURL)
            }
            catch {
                print("Failed to write JSON data: \(error.localizedDescription)")
            }
    }
}

Вот пример использования:

let newSiteKey = siteKey.loadJson(filename: "/Users/fakeUser/Documents/Dev/all.json")

Когда метод loadJson возвращает, newSiteKey будет содержать массив объектов класса SiteKey, через которые можно выполнить итерацию.

0 голосов
/ 28 января 2019

Представьте, что у вас есть массив кодируемых объектов

var array = [SiteKey]()

, тогда вы можете просто закодировать весь массив в Data, используя JSONEncoder

do {
    let encoded = try JSONEncoder().encode(array)
} catch { print(error) }

ToРасшифруйте Data в вашем массиве объектов, которые вы можете использовать JSONDecoder

do {
    array = try JSONDecoder().decode([SiteKey].self, from: encoded)
} catch { print(error) }

Мои предложения:

  • вместо этого создайте структуру вашего класса, тогда вы можете удалить hard-кодированный init, поскольку вы получаете одну бесплатно
  • имен переменных с маленькой заглавной буквой, а затем используете ключи кодирования для переименования во время кодирования / декодирования

struct SiteKey : Codable {

    var key : String
    var maxLength : Int
    var hasSpecialChars : Bool
    var hasUpperCase : Bool

    enum CodingKeys: String, CodingKey {
        case key = "Key"
        case maxLength = "MaxLength"
        case hasSpecialChars = "HasSpecialChars"
        case hasUpperCase = "HasUpperCase"
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...