Victor Hooi writes: > I'm reading JSON output from an input file, and extracting values. > > Many of the fields are meant to be numerical, however, some fields are > wrapped in a "floatApprox" dict, which messed with my parsing. > > For example: > > { > "hostname": "example.com", > "version": "3.0.5", > "pid": { > "floatApprox": 18403 > } > "network": { > "bytesIn": 123123, > "bytesOut": { > "floatApprox": 213123123 > } > } > > The floatApprox wrapping appears to happen sporadically in the input. > > I'd like to find a way to deal with this robustly.
So you want a value as is when it is a number - either an int or a float. And otherwise the value is a dict and you want the value at a known key. Here's a literal-minded expression of the spec: ( o if isinstance(o, (int, float)) else o['floatApprox'] ) > For example, I have the following function: > > def strip_floatApprox_wrapping(field): > # Extracts a integer value from a field. Workaround for the > # float_approx wrapping. > try: > return int(field) > except TypeError: > return int(field['floatApprox']) > > which I can then call on each field I want to extract. > > However, this relies on casting to int, which will only work for ints > - for some fields, they may actually be floats, and I'd like to > preserve that if possible. You could try int first, float second; you should still return the actual value. try: int(field) return field except TypeError: pass try: float(field) return field: except TypeError: return field['floatApprox'] There are a couple of reasons to return the actual value instead of the result of the "cast". First, it appears to be what you want :) Second, it allows you to have some confidence that the data actually is numeric and not, say, strings that happen to look like numbers. > (I know there's a isnumber() field - but you can only call that on a > string - so if I do hit a floatApprox field, it will trigger a > AttributeError exception, which seems a bit clunky to handle). > > def strip_floatApprox_wrapping(field): > # Extracts a integer value from a field. Workaround for the > # float_approx wrapping. > try: > if field.isnumeric(): > return field > except AttributeError: > return field['floatApprox'] I take it you haven't tried this and the fields in question actually are numeric, not strings. That exception would be taken for a wrong reason. You could do the following, but str.isnumeric does not do what you want. For example, "3.14".isnumeric() is as False as "{}".isnumeric(). if str(field).isnumeric(): return field else: return field['floatApprox'] > Is there a way to re-write strip_floatApprox_wrapping to handle both > ints/floats, and preserve the original format? > > Or is there a more elegant way to deal with the arbitrary nesting with > floatApprox? Consider ... if isinstance(field, (int, float)) else ... . -- https://mail.python.org/mailman/listinfo/python-list