Fixing Tricky JSON Decoding Issues
This morning I've been fighting a problem that one of my web clients has been seeing. They are hitting the greek engine and trying to calculate implied vols for given option quotes (bid/ask). When they send me a value like 25.21, it works well, but 26.00 fails. Makes no sense to me, but then again, maybe I'm missing something.
So I make a little C++ test case and it checks out nicely. So far so good. I can put in just about any value and get reasonable values out. Nice. So what's the problem?
I ask the developer to send me exactly what he's sending me, just to make sure I know what it is, and that it's formatted properly. Here's what I got:
{ "values" : { "O:AAPL:20120121:400.00:C" : { "bid.price" : 26 }}, "instruments" : ["O:AAPL:20120121:400.00:C"] }
and the second I saw the request, I knew what it was: JSON doesn't like unnecessary data in it's encoding. THe number 26 was sent as 26 and not 26.00. The Broker then looked at this from JSON as an integer and it sent it to me as such. I was expecting a double, and so I passed on the value.
Obvious!
To clear up the problem I changed my code from:
if (key == "bid.price") { freeze(); mQuote.bid.price = dbl2int64((double)val); }
where val is the variant, and we're using the casting operator of the variant, to:
if (key == "bid.price") { freeze(); mQuote.bid.price = dbl2int64(toDouble(val)); }
where:
static inline double toDouble( const msg::ng::variant & aValue ) { double retval = NAN; if (aValue.isDouble()) { retval = (double)aVariant; } else if (aValue.isInteger()) { retval = (int64_t)aVariant; } else if (aValue.isString()) { retval = atof(((std::string &)aValue).c_str()); } return retval; }
Now I am sure the casting is being done properly, and the user can send me integers, doubles, and even strings that format into integers or doubles, and I don't have to make them deal with it. This is the kind of bug I like to find. The solution makes it even better than before. Nice.