Swift 4 decode simple root level json value

In iOS 13.1+ and macOS 10.15.1+ JSONDecoder can handle primitive types on root level.

See the latest comments (Oct 2019) in the linked article underneath Martin's answer.


It works with good ol' JSONSerialization and the .allowFragments reading option. From the documentation:

allowFragments

Specifies that the parser should allow top-level objects that are not an instance of NSArray or NSDictionary.

Example:

let json = "22".data(using: .utf8)!

if let value = (try? JSONSerialization.jsonObject(with: json, options: .allowFragments)) as? Int {
    print(value) // 22
}

However, JSONDecoder has no such option and does not accept top-level objects which are not arrays or dictionaries. One can see in the source code that the decode() method calls JSONSerialization.jsonObject() without any option:

open func decode<T : Decodable>(_ type: T.Type, from data: Data) throws -> T {
    let topLevel: Any
    do {
       topLevel = try JSONSerialization.jsonObject(with: data)
    } catch {
        throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: error))
    }

    // ...

    return value
}