如何将 Swift 4 编码的 JSON 写入文件?
How to write a Swift 4 encoded JSON to a file?
如何将通过 Swift 4 Codable 协议编码的 JSON 对象写入文件?在 Swift 4 之前,我在创建的数据(或字符串)上使用 JSONSerialization.writeJSONObject
,但现在 JSONSerialization.isValidJSONObject
returns 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")
Data is not a valid format for JSON serialization:
{"numOfTeeth":48,"hobbies":["Dancing","Swiming","Eating people"],"name":"Nancy","carnivorous":true}
Data is not a valid format for JSON serialization: Optional(99 bytes)
如何让它通过 JSON 验证,然后将其写入文件?
JSON序列化。您的 JSONSerialization.isValidJSONObject
用法有误。作为文档 states:
A Foundation object that may be converted to JSON must have the following properties:
• The top level object is an NSArray
or NSDictionary
.
• All objects are instances of NSString
, NSNumber
, NSArray
, NSDictionary
, or NSNull
.
• All dictionary keys are instances of 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
生成的,就不需要额外的验证 ;)
要添加到@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
将使用适当的缩进和换行符编写。
如何将通过 Swift 4 Codable 协议编码的 JSON 对象写入文件?在 Swift 4 之前,我在创建的数据(或字符串)上使用 JSONSerialization.writeJSONObject
,但现在 JSONSerialization.isValidJSONObject
returns 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")
Data is not a valid format for JSON serialization:
{"numOfTeeth":48,"hobbies":["Dancing","Swiming","Eating people"],"name":"Nancy","carnivorous":true}
Data is not a valid format for JSON serialization: Optional(99 bytes)
如何让它通过 JSON 验证,然后将其写入文件?
JSON序列化。您的 JSONSerialization.isValidJSONObject
用法有误。作为文档 states:
A Foundation object that may be converted to JSON must have the following properties:
• The top level object is anNSArray
orNSDictionary
.
• All objects are instances ofNSString
,NSNumber
,NSArray
,NSDictionary
, orNSNull
.
• All dictionary keys are instances ofNSString
.
因此,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
生成的,就不需要额外的验证 ;)
要添加到@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
将使用适当的缩进和换行符编写。