JSONKit icon indicating copy to clipboard operation
JSONKit copied to clipboard

Support for NSDecimal/NSDecimalNumber

Open allynbauer opened this issue 14 years ago • 6 comments

Any chance of adding this?

allynbauer avatar Aug 25 '11 19:08 allynbauer

Unlikely. I'm open to hearing arguments for adding it, though.

From my perspective, NSDecimalNumber doesn't really add much. It's also more than a bit quirky and doesn't seem to be something that receives a lot of love and attention from the folks at Apple.

I strongly suspect that one of the reasons why it exists at all is due to the fact that in a number of jurisdictions, you must use a base ten number format when manipulating numbers that are used in financial calculations. And if the law says you need to use base ten math when dealing with money, that's a pretty compelling reason.

But other than that, I don't see much of a compelling reason. Efforts to use it as some form of "extended precision" number object that can represent numbers that are > 64 bits, or can not be represented in a IEEE-754 double are probably misguided. And when you do use it for those kinds of cases, it tends to have a lot of unpredictable corner case effects when those objects interact with code that expects numbers to be represented by <= 64 bits / IEEE-754 double, which ultimately defeats the reason why turned to NSDecimalNumber in the first place- if the whole processing and manipulation path doesn't handle the NSDecimalNumber case correctly, why bother?

johnezang avatar Aug 25 '11 22:08 johnezang

Yeah, I see your point. That said, I am developing an application that needs to process financial information. I am using NSDecimalNumber for these values internally, they just get float-ified over JSON. If native support in JSONKit is not an option, perhaps you could help me understand what would need changed?

allynbauer avatar Aug 25 '11 22:08 allynbauer

In this particular case I would actually recommend using strings to represent the decimal numbers in question. If the numbers get converted to JSON Numbers, there's no guarantee that other JSON implementations will use a base ten number format to represent the numbers. On the other hand, a "10.15" string will (probably!) pass through unmolested and uninterpreted.

While JSON is great for a lot of things, the JSON RFC-4627 standard leaves a lot to be desired when it comes to the behavior required by implementations. The reality is that RFC 4627 is really nothing more than a trivial grammar for what is and isn't valid JSON. The grammar for numbers allows for arbitrarily and infinitely long numbers and is silent about the details of how any numbers must be handled by an implementation.

If you're dealing with numbers representing currency and are required by law to handle such numbers in a specific way, then JSON is probably a poor choice. Even if JSONKit was modified to use NSDecimalNumber it wouldn't do you much good in these cases- once serialized to JSON, you can no longer have any reasonable confidence that the number (which is assumed to be required by law to be manipulated using base ten arithmetic in this case) will not be "tainted" due to conversion to base two (i.e., IEEE-754 double). Same goes for any numbers you receive via JSON (i.e., not a "10.15" quoted number, but 10.15)- you can never be sure that the integrity of the number has been preserved by every recipient. Just think of a firewall that looks for suspicious JSON and sanitizes it in a way that is similar to a state-full firewall- the JSON is parsed, examined for "problems", and the parsed and deserialized result is then re-serialized back in to JSON.

I sympathize with you. You've certainly got a legitimate and compelling reason to need NSDecimalNumbers in JSONKit, but it's an extremely specific corner case. IMHO, it's also unlikely to achieve the behavior you require anyways when you factor everything else in.

My best recommendation is to switch to using strings to represent numbers. The current code for master allows you to easily intercept NSDecimalNumber objects being serialized and convert them in to NSString objects, which would then result in "10.15" style numbers. For deserializing, you'd have to write some post-processing code that knows which part of the JSON has "10.15" numbers and replace the NSString objects with NSDecimalNumber objects.

johnezang avatar Aug 25 '11 23:08 johnezang

Thank you for such a detailed response. I appreciate the time and wisdom.

allynbauer avatar Aug 26 '11 02:08 allynbauer

I had the same question. Thank you for your guidance. Couldn't you also serialize/deserialize decimals as objects? Would this be any safer than as strings?

ryankunz avatar Sep 01 '11 18:09 ryankunz

If JSONKit receives a JSON body as a string, wouldn't storing numbers as NSDecimalNumber effectively eliminate the floating-point parsing complexity you note in the readme? (NSDecimal numbers can be initialized by a string). So even if the instance of a value in the JSON body appears as a JSON number, realistically it's a string until you separate it out and store it, right? This wouldn't make JSONKit's job easier?

grgcombs avatar Sep 25 '13 16:09 grgcombs