如何将Swift 4编码的JSON写入文件?

时间:2017-10-16 05:34:26

标签: json swift serialization swift4 codable

如何将通过Swift 4 Codable协议编码的JSON对象写入文件?在使用Swift 4之前,我使用了JSONSerialization.writeJSONObject,但JSONSerialization.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序列化的有效格式:
  {&#34; numOfTeeth&#34;:48,&#34;爱好&#34;:[&#34;跳舞&#34;,&#34;游泳&#34;,&#34;吃人&#34;] &#34;名称&#34;:&#34;南西&#34;&#34;食肉&#34;:真}
  数据不是JSON序列化的有效格式:可选(99字节)

如何将其传递给JSON验证,然后将其写入文件?

2 个答案:

答案 0 :(得分:6)

<强> JSONSerialization 即可。您的JSONSerialization.isValidJSONObject用法错误。作为文档clearly states

  

可以转换为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)")
    }
}

只要标准JSONEncoder生成JSON数据,就不需要进行额外的验证;)

答案 1 :(得分:0)

要添加到@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 将以适当的缩进和换行符书写。