13

According to the JSON standard RFC 7159, this is valid json:

22

How do I decode this into an Int using swift4's decodable? This does not work

let twentyTwo = try? JSONDecoder().decode(Int.self, from: "22".data(using: .utf8)!)
10
  • 1
    this is not a valid json, a json is made by key and value pairs and it's just a value. Commented Oct 16, 2017 at 10:56
  • 3
    This is valid JSON fragment, not valid JSON. Commented Oct 16, 2017 at 10:56
  • 2
    If you wrap your try in a Do..Catch and handle the error, it will tell you that your json format is not correct. That is not a valid JSON, why are you insisting on this? Commented Oct 16, 2017 at 11:19
  • 2
    JSONSerialization has a allowFragments reading option for that purpose, but the new JSONDecoder has no such option. Commented Oct 16, 2017 at 11:19
  • 2
    @Desdenova I am not insisting, it is valid according to the RFC 7159 standard which is definitely being used widely. If what you are saying is true I guess this means swift is not using it though. Commented Oct 16, 2017 at 11:22

2 Answers 2

15

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
}
Sign up to request clarification or add additional context in comments.

2 Comments

You can try and file a bug report at Apple.
I forgot to write, this but I submitted an issue here bugs.swift.org/browse/SR-6163
5

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.