Python JSON parse_float=decimal.Decimal not working

Question:

I have a string with a floating point number in it, but I can’t get JSON to load it as a decimal.

x = u'{"14": [4.5899999999999999, "susan"]}'
json.loads(x, parse_float = decimal.Decimal)

This returns:

{u'14': [Decimal('4.5899999999999999'), u'susan']}

Any idea how I can make it into the actual “4.59”?

Asked By: victor

||

Answers:

You need to define a function that performs whatever rounding you desire, then uses the altered string to build the Decimal. Your current solution does work perfectly well: it just does exactly what you tell it to, i.e., use the entire string, as opposed to what you desire (and have not told either the code, or us;-).

E.g.:

>>> def doit(s): return decimal.Decimal(str(round(float(s), 2)))
... 
>>> json.loads(x, parse_float=doit)
{u'14': [Decimal('4.59'), u'susan']}
>>> 
Answered By: Alex Martelli

You can’t. That number isn’t 4.59, it’s 4.589999999999999999, as far as the json parser knows. You’d need to add some more complicated logic that rounds numbers like that, as a wrapper around decimal.Decimal.

Answered By: inklesspen

I know this is over a decade later, but just to refine the answer from Alex Martin a bit for anyone coming across this as I did on Google. We can simplify his function to:

json.loads(x, parse_float=lambda x: round(decimal.Decimal(x),2))

The reason is that the value passed into the parse_float callable by json.loads is already a str. Also, this code would not truncate the input value at 64 bits as his would (parsing to a float first will truncate at 64 bit precision).

Obviously, you could use a function rather than a lambda too. I just used the lambda here for brevity.

Answered By: UglyBug
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.