title: How to write a Swift 4 encoded JSON to a file?
body: <p>How do you write a JSON object encoded via Swift 4 Codable protocol to a file? Before Swift 4 I used <code>JSONSerialization.writeJSONObject</code> but <code>JSONSerialization.isValidJSONObject</code> now returns <code>false</code> on the created data (or string). An example:</p>
  
  <pre><code>import Foundation
  
  class Shark : Codable
  {
      var name:String = ""
      var carnivorous:Bool = true
      var numOfTeeth:Int = 0
      var hobbies:[String] = []
  }
  
  class JSON
  {
      class func encode&lt;T:Encodable&gt;(_ obj:T) -&gt; String?
      {
          if let encodedData = try? JSONEncoder().encode(obj)
          {
              return String(data: encodedData, encoding: .utf8)
          }
          return nil
      }
  
      class func writeToStream(data:Any, path:String) -&gt; 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: &amp;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")
  }
  </code></pre>
  
  <p>Both of these formats are invalid for <code>JSONSerialization.isValidJSONObject()</code>:</p>
  
  <pre><code>JSON.writeToStream(data: jsonString, path: "\(NSHomeDirectory())/Documents")
  JSON.writeToStream(data: jsonString.data(using: .utf8), path: "\(NSHomeDirectory())/Documents")
  </code></pre>
  
  <blockquote>
    <p>Data is not a valid format for JSON serialization:<br>
    {"numOfTeeth":48,"hobbies":["Dancing","Swiming","Eating people"],"name":"Nancy","carnivorous":true}<br>
    Data is not a valid format for JSON serialization: Optional(99 bytes)</p>
  </blockquote>
  
  <p>How do I get it passed for JSON validation and then write it to a file?</p>