簡體   English   中英

如何將 Swift 4 編碼的 JSON 寫入文件?

[英]How to write a Swift 4 encoded JSON to a file?

如何將通過 Swift 4 Codable 協議編碼的 JSON 對象寫入文件? 在 Swift 4 之前,我使用JSONSerialization.writeJSONObjectJSONSerialization.isValidJSONObject現在在創建的數據(或字符串)上返回false 一個例子:

import Foundation

class Shark : Codable
{
    var name:String = ""
    var carnivorous:Bool = true
    var numOfTeeth:Int = 0
    var hobbies:[String] = []
}

class JSON
{
    class func encode<T:Encodable>(_ obj:T) -> String?
    {
        if let encodedData = try? JSONEncoder().encode(obj)
        {
            return String(data: encodedData, encoding: .utf8)
        }
        return nil
    }

    class func writeToStream(data:Any, path:String) -> Bool
    {
        var success = false
        if JSONSerialization.isValidJSONObject(data)
        {
            if let stream = OutputStream(toFileAtPath: "\(path)", append: false)
            {
                stream.open()
                var error:NSError?
                JSONSerialization.writeJSONObject(data, to: stream, options: [], error: &error)
                stream.close()
                if let error = error
                {
                    print("Failed to write JSON data: \(error.localizedDescription)")
                    success = false
                }
            }
            else
            {
                print("Could not open JSON file stream at \(path).")
                success = false
            }
        }
        else
        {
            print("Data is not a valid format for JSON serialization: \(data)")
            success = false
        }
        return success
    }
}


let shark = Shark()
shark.name = "Nancy"
shark.carnivorous = true
shark.numOfTeeth = 48
shark.hobbies = ["Dancing", "Swiming", "Eating people"]

if let jsonString = JSON.encode(shark)
{
    let success = JSON.writeToStream(data: jsonString.data(using: .utf8), path: "\(NSHomeDirectory())/Documents")
}

這兩種格式對於JSONSerialization.isValidJSONObject()都是無效的:

JSON.writeToStream(data: jsonString, path: "\(NSHomeDirectory())/Documents")
JSON.writeToStream(data: jsonString.data(using: .utf8), path: "\(NSHomeDirectory())/Documents")

數據不是 JSON 序列化的有效格式:
{"numOfTeeth":48,"hobbies":["Dancing","Swiming","Eating people"],"name":"Nancy","carnivorous":true}
數據不是 JSON 序列化的有效格式:可選(99 字節)

如何讓它通過 JSON 驗證,然后將其寫入文件?

JSON 序列化 您的JSONSerialization.isValidJSONObject用法是錯誤的。 正如文檔所述

可以轉換為 JSON 的 Foundation 對象必須具有以下屬性:
• 頂級對象是NSArrayNSDictionary
• 所有對象都是NSStringNSNumberNSArrayNSDictionaryNSNull
• 所有字典鍵都是NSString實例。

因此, DataString類型根本無效;)

寫入編碼數據 要實際寫入生成的Data ,請改用相應的Data.write(to: URL)方法。 例如:

if let encodedData = try? JSONEncoder().encode(obj) {
    let path = "/path/to/obj.json"
    let pathAsURL = URL(fileURLWithPath: path)
    do {
        try encodedData.write(to: pathAsURL)
    } 
    catch {
        print("Failed to write JSON data: \(error.localizedDescription)")
    }
}

只要 JSON 數據是由標准JSONEncoder生成的, JSONEncoder不需要額外的驗證;)

添加到@Paulo答案,也可能具有JSONEncoder指定輸出以類似的方式與格式JSONSerialization 為此,您需要創建一個JSONEncoder實例並將其outputFormatting屬性設置為您想要的值(它必須是JSONEncoder.OutputFormatting的實例)。

示例:

let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted

if let encodedData = try? encoder.encode(obj) {
    let path = "/path/to/obj.json"
    let pathAsURL = URL(fileURLWithPath: path)
    do {
        try encodedData.write(to: pathAsURL)
    } 
    catch {
        print("Failed to write JSON data: \(error.localizedDescription)")
    }
}

現在將使用適當的縮進和換行符寫入encodedData

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM