How to write a Swift 4 encoded JSON to a file?
JSONSerialization. Your JSONSerialization.isValidJSONObject
usage is wrong. As the documentation 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
.
As such, Data
or String
types aren’t valid at all ;)
Writing the encoded data. To actually write the generated Data
, use the corresponding Data.write(to: URL)
method instead. For instance:
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)")
}
}
As long as the JSON data is generated by the standard JSONEncoder
no additional validation is really made necessary ;)
BadmintonCat
iOS / Mac OSX / Unity3D developer and former Flash/AS3 developer in Tokyo, Japan. Also delving into C# .NET development.
Updated on June 14, 2022Comments
-
BadmintonCat about 2 years
How do you write a JSON object encoded via Swift 4 Codable protocol to a file? Before Swift 4 I used
JSONSerialization.writeJSONObject
butJSONSerialization.isValidJSONObject
now returnsfalse
on the created data (or string). An example: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") }
Both of these formats are invalid for
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)How do I get it passed for JSON validation and then write it to a file?