I am making api calls and receive a response back in json like so
result = {'foo': '123.456', 'bar': '23', 'donald': 'trump', 'time': '2016-04-07T05:31:49.532124Z'}
Although result is either a dictionary or a list, the contents are always strings. I want to cast these values to the appropriate type. (ie '123.456'
to a float, '23'
to an int, 'time'
to a datetime.)
My code works but it seems like there should be a simpler/more efficient way to do this. Is there?
Here's my version
from dateutil.parser import parse
def is_float(x):
try:
float(x)
return True
except ValueError:
return False
def is_int(x):
try:
a = float(x)
b = int(a)
except ValueError:
return False
else:
return a == b
def is_datetime(x):
try:
parse(x)
return True
except ValueError:
return False
def smartcast(x):
if isinstance(x, dict):
return { k:smartcast(v) for k, v in x.items() }
elif isinstance(x, list):
return map(smartcast, x)
elif is_int(x):
return int(x)
elif is_float(x):
return float(x)
elif is_datetime(x):
return parse(x)
else:
return x
Edit: If possible I'd like to avoid using try
and except
. I'd like to implement this into an asynchronous twisted program and I think try
and except
block so it just makes the program synchronous. I'm new to twisted so I'm not sure if that is true.
As per Francesco's solution, here's the updated code.
from dateutil.parser import parse
def smartcast(x):
if isinstance(x, dict):
return { k:smartcast(v) for k, v in x.items() }
elif isinstance(x, list):
return map(smartcast, x)
else:
for t in [int, float, parse]:
try:
return t(x)
except ValueError:
continue
return x
And what is the appropriate type ? I am asking this to underline that sometimes also for humans it is not clear what the type is: are you sure that "42" is always an int or sometimes it has to be considered just as a string?
Anyway, as you did, you can build your solution with your rules that makes sense in your context.
In your case, you can simplify your code with a simple loop
from dateutil.parser import parse
tests = [int, float, parse]
def smartcast(value):
for test in tests:
try:
return test(value)
except ValueError:
continue
# No match
return value
what about using ast.literal_eval()?
https://docs.python.org/2/library/ast.html#ast.literal_eval
voting up Francesco's answer. You need an exception raised.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.