web-dev-qa-db-ja.com

Swift 4エンコードされたJSONをファイルに書き込む方法は?

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シリアル化の有効な形式ではありません:
{"numOfTeeth":48、 "hobbies":["Dancing"、 "Swimming"、 "Eating people"]、 "name": "Nancy"、 "carnivorous":true}
データはJSONシリアル化の有効な形式ではありません:オプション(99バイト)

JSON検証に合格してからファイルに書き込むにはどうすればよいですか?

6
BadmintonCat

JSONSerialization。 _JSONSerialization.isValidJSONObject_の使用法が間違っています。ドキュメントとして 明確に述べています

JSONに変換できるFoundationオブジェクトには、次のプロパティが必要です。
•最上位のオブジェクトはNSArrayまたはNSDictionaryです。
•すべてのオブジェクトは、NSStringNSNumberNSArrayNSDictionary、またはNSNullのインスタンスです。
•すべての辞書キーはNSStringのインスタンスです。

そのため、DataまたはStringタイプはまったく有効ではありません;)

エンコードされたデータの書き込み。生成された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によって生成されている限り、追加の検証は実際には必要ありません;)

12
Paulo Mattos