About Me

JSON Encoder Change in Swift 5.1

Today I started to update my app for the iOS 13 SDK and came across a surprising bug caused by a change in the JSONEncoder.

On previous operating systems, JSONEncoder did not support encoding top-level values, but now, on the latest operating systems (iOS 13, macOS 10.15, watchOS 6, and tvOS 13) with Swift 5.1, it does.

This simple bit of code demonstrates it.

do {
    let data = try JSONEncoder()
        .encode("myString")
    let output = String(data: data, encoding: .utf8)!
    print("Success: \(output)")
}
catch {
    print("Error: \(error)")
}

With previous operating systems we get the following output:

Error: invalidValue("myString", Swift.EncodingError.Context(codingPath: [], debugDescription: "Top-level String encoded as string JSON fragment.", underlyingError: nil))

However, when we run this on the latest OSs, we encode it successfully:

Success: "myString"

Notice that it simply puts quotes around the string.

This also includes booleans, numbers, and null, all of which are valid JSON on their own.

Important: JSONEncoder still fails to encode top-level values when using the latest SDKs and Swift 5.1 if you are targeting previous OSs. If you are going to depend on this functionality, you must make sure to only do so on the latest OSs.

Arguably I should not have been relying on this behavior in the first place, but I wanted to let you know in case this will cause any of your existing code to break as well.