summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Spinler <spinler@us.ibm.com>2018-06-25 14:11:58 -0500
committerBrad Bishop <bradleyb@fuzziesquirrel.com>2018-08-28 01:09:41 +0000
commit6691e7ca4e2adf52bac1fc3a82ed35adfce4349c (patch)
treeeb646e7aed71f4f09c1c06508209282f9f5950a5
parenta8b05d161ef3367f3fc2f4a5e44a2b0b69a9f3d2 (diff)
downloadphosphor-rest-server-6691e7ca4e2adf52bac1fc3a82ed35adfce4349c.zip
phosphor-rest-server-6691e7ca4e2adf52bac1fc3a82ed35adfce4349c.tar.gz
Explicitly convert dbus.Booleans to bools
The dbus.Boolean data type that the dbus python module uses for booleans is based on an int, so the JSON encoder class serializes it to a 1 and 0 instead of the native JSON bool presentation of true and false. Though the encoder module does allow for custom serialization functions, it only does so for data types that it doesn't recognize, and it does recognize a dbus.Boolean though it thinks it's an int. To get around this limitation, walk the response dictionary object and convert all dbus.Booleans to bools before encoding the response. The only time that data is copied is when a boolean is in a dbus.Struct, which is an immutable tuple, so it will be made into a list during revision before converting it back when complete. There is a slight performance penalty to pay for this. Measurements showed enumerating the whole /xyz/openbmc_project tree take about 1 second longer. Resolves openbmc/openbmc#3154 Tested: Lots of REST calls and output inspection. Change-Id: I591f010798a80aeafd02289e3d35c335540f6562 Signed-off-by: Matt Spinler <spinler@us.ibm.com>
-rw-r--r--module/obmc/wsgi/apps/rest_dbus.py41
1 files changed, 41 insertions, 0 deletions
diff --git a/module/obmc/wsgi/apps/rest_dbus.py b/module/obmc/wsgi/apps/rest_dbus.py
index 9cb69f0..badc550 100644
--- a/module/obmc/wsgi/apps/rest_dbus.py
+++ b/module/obmc/wsgi/apps/rest_dbus.py
@@ -1381,6 +1381,46 @@ class JsonApiResponsePlugin(object):
def __init__(self, app):
app.install_error_callback(self.error_callback)
+ @staticmethod
+ def dbus_boolean_to_bool(data):
+ ''' Convert all dbus.Booleans to true/false instead of 1/0 as
+ the JSON encoder thinks they're ints. Note that unlike
+ dicts and lists, tuples (from a dbus.Struct) are immutable
+ so they need special handling. '''
+
+ def walkdict(data):
+ for key, value in data.items():
+ if isinstance(value, dbus.Boolean):
+ data[key] = bool(value)
+ elif isinstance(value, tuple):
+ data[key] = walktuple(value)
+ else:
+ JsonApiResponsePlugin.dbus_boolean_to_bool(value)
+
+ def walklist(data):
+ for i in range(len(data)):
+ if isinstance(data[i], dbus.Boolean):
+ data[i] = bool(data[i])
+ elif isinstance(data[i], tuple):
+ data[i] = walktuple(data[i])
+ else:
+ JsonApiResponsePlugin.dbus_boolean_to_bool(data[i])
+
+ def walktuple(data):
+ new = []
+ for item in data:
+ if isinstance(item, dbus.Boolean):
+ item = bool(item)
+ else:
+ JsonApiResponsePlugin.dbus_boolean_to_bool(item)
+ new.append(item)
+ return tuple(new)
+
+ if isinstance(data, dict):
+ walkdict(data)
+ elif isinstance(data, list):
+ walklist(data)
+
def apply(self, callback, route):
skip = getattr(
route.get_undecorated_callback(), 'suppress_json_resp', None)
@@ -1389,6 +1429,7 @@ class JsonApiResponsePlugin(object):
def wrap(*a, **kw):
data = callback(*a, **kw)
+ JsonApiResponsePlugin.dbus_boolean_to_bool(data)
if self.has_body():
resp = {'data': data}
resp['status'] = 'ok'
OpenPOWER on IntegriCloud