Why is Data class not Codable so it can be JSON encoded?

Due to the current awful state of the doc, I cannot figure out why the doc implies you could encode Data into JSON, but you cannot.
1) JSONEncoder/JSONDecoder requires Codable protocol adopting objects.
2) Codable is just Encodable & Decodable
3) The Data class conforms to Encodable & Decodable
4) The JSONEncoder & JSONDecoder classes have a property (dataEncodingStrategy,dataDecodingStrategy) to determine how to deal with raw data (default if base64)

BUT Data does not adopt the Codable protocol (only Encodable & Decodable) so JSONEncoder fails if you try to include Data.


Why? What are those properties for on JSONEncoder/JSONDecoder if not related to Data? Why not take the extra step and declare Data Codable as it already conforms to it's components?

Accepted Reply

This isn't accurate. Your points 1, 2, 3 and 4 are correct. But it doesn't matter whether Data adopts Codable or just Encodable & Decodable. Codable only exists as a convenience to avoid writing Encodable & Decodable.


There isn't (or at least shouldn't be) any API that demands explict Codable conformance. JSONEncoder requires values conforming to Encodable, and JSONDecoder requires values conforming to Decodable. Data conforms to both protocols, so works with both JSON classes.


You can see this for yourself in a playground:


let d = Data(repeating: 1, count: 10)
let r = try! JSONEncoder().encode([d])
print(String(data: r, encoding: .utf8)!)
// prints: ["AQEBAQEBAQEBAQ=="]


Note that you can't encode just "d" in line 2, because the default behavior is to require an array or dictionary at the top level.


I'm not sure exactly what problem you ran into, but encoding and decoding Data should be very easy.

Replies

Now that I have gotten the rant out of my system... I understand that JSON doesn't support raw data but what I am talking about is simply a convenience. You can readily turn Data into a base64 string and it looks like Apple was heading there.

This isn't accurate. Your points 1, 2, 3 and 4 are correct. But it doesn't matter whether Data adopts Codable or just Encodable & Decodable. Codable only exists as a convenience to avoid writing Encodable & Decodable.


There isn't (or at least shouldn't be) any API that demands explict Codable conformance. JSONEncoder requires values conforming to Encodable, and JSONDecoder requires values conforming to Decodable. Data conforms to both protocols, so works with both JSON classes.


You can see this for yourself in a playground:


let d = Data(repeating: 1, count: 10)
let r = try! JSONEncoder().encode([d])
print(String(data: r, encoding: .utf8)!)
// prints: ["AQEBAQEBAQEBAQ=="]


Note that you can't encode just "d" in line 2, because the default behavior is to require an array or dictionary at the top level.


I'm not sure exactly what problem you ran into, but encoding and decoding Data should be very easy.