Advertisement
Guest User

Untitled

a guest
Sep 15th, 2019
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.88 KB | None | 0 0
  1. from functools import singledispatch
  2. from itertools import chain
  3. from typing import (Any,
  4. Dict,
  5. Iterable,
  6. List)
  7.  
  8. Record = Dict[str, Any]
  9.  
  10.  
  11. def flatten(object_: Record,
  12. *,
  13. path_separator: str = '.') -> Iterable[Record]:
  14. """
  15. Flattens given JSON object into list of objects with non-nested values.
  16.  
  17. >>> flatten({'a': 1})
  18. [{'a': 1}]
  19. >>> flatten({'a': [1, 2]})
  20. [{'a': 1}, {'a': 2}]
  21. >>> flatten({'a': {'b': None}})
  22. [{'a.b': None}]
  23. """
  24. keys = set(object_)
  25. result = [dict(object_)]
  26. while keys:
  27. key = keys.pop()
  28. new_result = []
  29. for index, record in enumerate(result):
  30. try:
  31. value = record[key]
  32. except KeyError:
  33. new_result.append(record)
  34. else:
  35. if isinstance(value, dict):
  36. del record[key]
  37. new_value = flatten_nested_objects(
  38. value,
  39. prefix=key + path_separator,
  40. path_separator=path_separator)
  41. keys.update(new_value.keys())
  42. new_result.append({**new_value, **record})
  43. elif isinstance(value, list):
  44. del record[key]
  45. new_value = [
  46. flatten_nested_objects(sub_value,
  47. prefix=key + path_separator,
  48. path_separator=path_separator)
  49. for sub_value in value]
  50. keys.update(chain.from_iterable(map(dict.keys, new_value)))
  51. new_result.extend({**sub_value, **record}
  52. for sub_value in new_value)
  53. else:
  54. new_result.append(record)
  55. result = new_result
  56. return result
  57.  
  58.  
  59. @singledispatch
  60. def flatten_nested_objects(object_: Any,
  61. *,
  62. prefix: str = '',
  63. path_separator: str) -> Any:
  64. return {prefix[:-len(path_separator)]: object_}
  65.  
  66.  
  67. @flatten_nested_objects.register(dict)
  68. def _(object_: Record,
  69. *,
  70. prefix: str = '',
  71. path_separator: str) -> Record:
  72. result = dict(object_)
  73. for key in list(result):
  74. result.update(flatten_nested_objects(result.pop(key),
  75. prefix=(prefix + key
  76. + path_separator),
  77. path_separator=path_separator))
  78. return result
  79.  
  80.  
  81. @flatten_nested_objects.register(list)
  82. def _(object_: List,
  83. *,
  84. prefix: str = '',
  85. path_separator: str) -> Record:
  86. return {prefix[:-len(path_separator)]: list(map(flatten_nested_objects,
  87. object_))}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement