Sign in to run and submit your work
Reading is open to everyone. Running code and saving drafts need an account so your work is yours and comes back on your next visit.
or
CODE WORKSPACE
The warehouse loader wants one flat column per field, but the producer sends arbitrarily nested JSON: objects inside objects, and lists of objects.
Write flatten_payload(payload). It takes one payload and returns a single flat dict whose keys are the path to each value, joined with dots.
Function to write
flatten_payload(payload: dict) -> dictA flat dict whose keys are dotted paths and whose values are the leaves.
How to approach it
Decide what counts as a leaf first — then the recursion writes itself.
Sample cases
+ 2 held back until you submit
a nested event
Every rule at once: nested dicts, a list of dicts, a None leaf, and two empty containers.
Input
Argument 1
{
'event': 'checkout',
'user': {
'id': 'u1',
'geo': {
'country': 'IN',
'city': None
}
},
'items': [
{
'sku': 'A1',
'qty': 2
},
{
'sku': 'B2',
'qty': 1
}
],
'flags': {},
'tags': []
}Returns
{
'event': 'checkout',
'user.id': 'u1',
'user.geo.country': 'IN',
'user.geo.city': None,
'items.0.sku': 'A1',
'items.0.qty': 2,
'items.1.sku': 'B2',
'items.1.qty': 1,
'flags': {},
'tags': []
}already flat
Nothing to descend into — the payload comes back unchanged.
Input
Argument 1
{
'id': 'e1',
'amount': 12.5,
'ok': True
}Returns
{
'id': 'e1',
'amount': 12.5,
'ok': True
}a list of scalars
Lists are indexed by position, so three scores become three keys.
Input
Argument 1
{
'scores': [
10,
20,
30
],
'note': None
}Returns
{
'scores.0': 10,
'scores.1': 20,
'scores.2': 30,
'note': None
}Constraints
{'user': {'id': 'u1'}} becomes {'user.id': 'u1'}.{'scores': [10, 20]} becomes {'scores.0': 10, 'scores.1': 20}.{'flags': {}} stays {'flags': {}}.None is a value, not an absence. Keep it.Worked example
{'user': {'geo': {'country': 'IN', 'city': None}}} flattens to {'user.geo.country': 'IN', 'user.geo.city': None} — the None is kept, because a field that was explicitly null is different from a field that was never sent.
The rule that catches most people is 'flags': {}. The obvious recursion descends into it, finds no keys, adds nothing, and the column disappears from the output entirely — silently, with no error to notice.
What this tests
Recursion over a heterogeneous structure, and the discipline of deciding what a leaf is before writing the walk. Empty containers are the case that separates a flattener that works from one that quietly loses columns.
flatten_payload(payload: dict) -> dictSubmit for review to find out what your query gets right, what it gets wrong, and how it compares with the best working query for this exercise.
This scenario runs a full workspace — editor, canvas and results side by side. It needs a laptop or desktop to be usable. Open this page on a bigger screen to start building.