Flatten nested JSON into a string map
Company: Salesforce
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Onsite
Quick Answer: This question evaluates proficiency with JSON data structures, hierarchical traversal, and serialization, testing competency in handling nested objects and arrays, primitive values, and edge cases such as deep nesting and empty containers.
Constraints
- The structure contains only JSON-compatible types: object/dict, array/list, string, number, boolean, and null/None.
- 0 <= total number of container entries and primitive values <= 10^5.
- Object keys do not contain `.`, `[` or `]`.
- Empty objects and arrays are skipped and do not create entries in the flattened output.
Examples
Input: ({'a': 1, 'b': {'c': 2, 'd': [3, 4]}, 'e': [{'f': 5}]},)
Expected Output: '{"a":1,"b.c":2,"b.d[0]":3,"b.d[1]":4,"e[0].f":5}'
Explanation: Each primitive leaf becomes one entry: `a`, `b.c`, `b.d[0]`, `b.d[1]`, and `e[0].f`.
Input: ({'x': None, 'y': True, 'z': {}, 'w': [], 'a': {'b': False}},)
Expected Output: '{"a.b":false,"x":null,"y":true}'
Explanation: Only primitive values are emitted. Empty containers `z` and `w` are skipped.
Input: ({},)
Expected Output: '{}'
Explanation: There are no primitive leaves, so the flattened map is empty.
Input: ('{"user":{"name":"ann","tags":["x","y"]},"active":false}',)
Expected Output: '{"active":false,"user.name":"ann","user.tags[0]":"x","user.tags[1]":"y"}'
Explanation: The function also accepts a JSON string, parses it, flattens it, and serializes the sorted result.
Input: ([{'a': 1}, 2, [], {'b': [None, {'c': 3}]}],)
Expected Output: '{"[0].a":1,"[1]":2,"[3].b[0]":null,"[3].b[1].c":3}'
Explanation: When the root is an array, paths start with `[index]`. The empty array at index 2 is skipped.
Solution
def solution(data):
import json
if isinstance(data, str):
data = json.loads(data)
flat = {}
stack = [("", data)]
while stack:
path, value = stack.pop()
if isinstance(value, dict):
if not value:
continue
for key, child in value.items():
new_path = f"{path}.{key}" if path else str(key)
stack.append((new_path, child))
elif isinstance(value, list):
if not value:
continue
for i, child in enumerate(value):
new_path = f"{path}[{i}]" if path else f"[{i}]"
stack.append((new_path, child))
else:
flat[path] = value
return json.dumps(flat, sort_keys=True, separators=(",", ":"))Time complexity: O(n + m log m), where n is the total number of visited nodes and m is the number of flattened entries.. Space complexity: O(n).
Hints
- Use an explicit stack of `(path, value)` pairs instead of recursion so very deep nesting does not cause a recursion-depth error.
- Only write to the answer map when the current value is a primitive. If it is a dict or list, extend the path and keep traversing.