Fix for DecodingError "Expected to decode Double but found Int instead." - #22
Fix for DecodingError "Expected to decode Double but found Int instead."#22andrewash wants to merge 1 commit into
Conversation
Int literals cannot be cast as a Double using `as?` so `Double(<Int>)` must be used instead. JSON has only one Number type, and allows "5" to be considered a Double, not just "5.0"
shanecowherd
left a comment
There was a problem hiding this comment.
Do we need to address any other types?
andrewash
commented
Dec 1, 2023
Thank you Shane! @tattn it's my colleague @shanecowherd commenting above. Shane, I won't need anything beyond Double that I can foresee right now. Float would probably be a good choice for the library more generally. @tattn probably knows what types are otherwise supported by the library. |
tattn
commented
Dec 3, 2023
Thank you for your PR 👍 I created Could you please share the use case? |
andrewash
commented
Dec 6, 2023
Thank you for your feedback @tattn I'm happy to share our use case which may be surprising. I'll try to explain the use case simply:
Unfortunately in JSON, a Double like "1.00" can be written as "1" and so RN sends @tattn Would you be open to supporting this use case in your library if it's not a lot of extra work? If you do decide to support this use case, this PR would be needed for that. If you don't want to support this use case, then I can maintain a fork of your repo at my company's organization and keep the fix localized to that fork. That's ok too. Example: Here is the function definition, in Swift, of a RN NativeModule function. This is what's called by JS. |
@andrewash I haven't used React Native in a production environment, so I wasn't aware of the issue where Double is converted to Int when treated as JSON in data transmission. This seems like a problematic specification 😢 Using DictionaryDecoder as a JSON decoder is an interesting idea, but overly flexible decoding might delay the detection of implementation errors. Here's what I suggest:
For 1: letdecoder=DictionaryDecoder()
decoder.decodingStrategy =.json
try decoder.decode(JSON.self, from: jsonDictionary)Setting For 2: structRNDouble:Decodable,Equatable{varvalue:Doubleinit(_ value:Double){self.value = value
}init(from decoder:Decoder)throws{letcontainer=try decoder.singleValueContainer()do{
value =try container.decode(Double.self)}catch{
value =Double(try container.decode(Int.self))}}}structModel:Decodable,Equatable{letdouble:RNDouble}This approach directly addresses the issue but might be slightly cumbersome due to type nesting. What are your thoughts on these proposals? |
Related Issue
#21
Description
Int literals cannot be cast as a Double using
as?soDouble(<Int>)must be used instead.JSON has only one Number type, and allows "5" to be considered a Double, not just "5.0"
However MoreCodable's DictionaryDecoder always decoded "3" as an Int so we would need a way to convert it to a Double to support JSON's flexible number formats.
Testing
I've included a new unit test that fails before this PR, and passes once the change is made to
func castOrThrow<T>()References
This railroad from json.org shows that
3is totally valid as a JSON number