blob: a5b2c23640fa98ad887c57c775629b9325e144b0 [file] [log] [blame]
# -*- coding: utf-8 -*-
# Copyright 2017 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""A convenience class for objects which can be converted to JSON."""
from __future__ import print_function
import sys
assert sys.version_info >= (3, 6), 'This module requires Python 3.6+'
_BUILTINS = (str, int, float, bool, type(None))
class Structured(object):
"""An object with a whitelisted set of public properties (.VISIBLE_KEYS)"""
def _Keys(self):
seen = set()
for cls in type(self).mro():
for k in getattr(cls, 'VISIBLE_KEYS', ()):
if k not in seen:
yield k
def ToDict(self):
return ToStructure(self)
def ToStructure(value):
"""Makes an object JSON-encodable.
value: An object which can be converted to a JSON-encodable object.
An object which is legal to pass into json.dumps(obj), namely
type JSONEncodable = (
str | int | float | NoneType | dict<str, JSONEncodable> |
StackOverflow if the object has circular references (parent -> child ->
if isinstance(value, _BUILTINS):
return value
elif hasattr(value, '_Keys'):
ret = {}
for k in value._Keys(): # pylint: disable=protected-access
v = ToStructure(getattr(value, k, None))
if v is not None:
ret[k] = v
return ret
elif isinstance(value, dict):
ret = {}
for k, v in value.items():
v = ToStructure(v)
if v is not None:
ret[k] = v
return ret
iterator = iter(value)
except TypeError:
return None
ret = []
for element in iterator:
v = ToStructure(element)
if v is not None:
return ret