load_campaigns_from_csv hands you a clean list of campaign dicts. The CFO now wants that data in her dashboard — and the dashboard team asked for a JSON file. What does JSON look like compared to the CSV you just parsed?
load_campaigns_from_csv hands back a list of dicts — clean names, typed spend and leads. JSON looks like that same structure but written as text: keys in quotes, curly braces, nested. I've seen it in API responses but never produced it.
You've already got the hard part — the data is a Python list of dicts, and JSON is that structure written as a string. json.dumps is the bridge. Pass it your list, add indent=2 for readable formatting, and you get a string the dashboard team can paste straight into their config:
import json
campaigns = [
{"name": "email blast", "channel": "email", "spend": 1250.0, "leads": 50, "active": True},
{"name": "paid search", "channel": "paid_search", "spend": 12400.0, "leads": 52, "active": False}
]
json_str = json.dumps(campaigns, indent=2)
print(json_str)
# [
# {
# "name": "email blast",
# "channel": "email",
# "spend": 1250.0,
# "leads": 50,
# "active": true
# },
# ...
# ]So json.dumps returns a string, not a file? I expected it to write something to disk.
Right — dumps is "dump to string". You'd pass that string to open().write() if you wanted a file, or to a dashboard API if you're posting it. The function's job is just the conversion. And the reverse is json.loads: give it a JSON string, get back a Python list or dict. Round-trip — string in, object out, object in, string out.
So json.loads(json.dumps(data)) == data is always true? That's a built-in correctness check — if a round-trip produces the same structure, the serialisation is lossless.
You just independently invented the round-trip test. That's exactly what test suites do for JSON serialisers. Now put it together:
import json
def campaigns_to_json(campaigns: list) -> str:
result = json.dumps(campaigns, indent=2)
print(f"Serialised {len(campaigns)} campaigns to JSON")
return resultSix lines including the import, and the CFO gets a dashboard-ready export. load_campaigns_from_csv reads the Salesforce dump, campaigns_to_json writes the output. That's a two-function pipeline from raw export to structured handoff.
And the shape stays true to the source data — no information lost, no manual reformatting. One pitfall: json.dumps only accepts JSON-serialisable types. Python datetime objects, sets, and custom class instances raise a TypeError. Keep your dicts to strings, numbers, booleans, and None and you'll never hit that wall.
json.dumps(obj, indent=2) converts any JSON-serialisable Python object to a formatted string. json.loads(text) reverses it.
| Python | JSON |
|---|---|
True / False | true / false |
None | null |
str, int, float | same |
dumps vs dump — dumps returns a string; dump writes to a file object.indent omitted — output is one dense line, unreadable by humans.TypeError at runtime; keep dicts to primitive types.load_campaigns_from_csv hands you a clean list of campaign dicts. The CFO now wants that data in her dashboard — and the dashboard team asked for a JSON file. What does JSON look like compared to the CSV you just parsed?
load_campaigns_from_csv hands back a list of dicts — clean names, typed spend and leads. JSON looks like that same structure but written as text: keys in quotes, curly braces, nested. I've seen it in API responses but never produced it.
You've already got the hard part — the data is a Python list of dicts, and JSON is that structure written as a string. json.dumps is the bridge. Pass it your list, add indent=2 for readable formatting, and you get a string the dashboard team can paste straight into their config:
import json
campaigns = [
{"name": "email blast", "channel": "email", "spend": 1250.0, "leads": 50, "active": True},
{"name": "paid search", "channel": "paid_search", "spend": 12400.0, "leads": 52, "active": False}
]
json_str = json.dumps(campaigns, indent=2)
print(json_str)
# [
# {
# "name": "email blast",
# "channel": "email",
# "spend": 1250.0,
# "leads": 50,
# "active": true
# },
# ...
# ]So json.dumps returns a string, not a file? I expected it to write something to disk.
Right — dumps is "dump to string". You'd pass that string to open().write() if you wanted a file, or to a dashboard API if you're posting it. The function's job is just the conversion. And the reverse is json.loads: give it a JSON string, get back a Python list or dict. Round-trip — string in, object out, object in, string out.
So json.loads(json.dumps(data)) == data is always true? That's a built-in correctness check — if a round-trip produces the same structure, the serialisation is lossless.
You just independently invented the round-trip test. That's exactly what test suites do for JSON serialisers. Now put it together:
import json
def campaigns_to_json(campaigns: list) -> str:
result = json.dumps(campaigns, indent=2)
print(f"Serialised {len(campaigns)} campaigns to JSON")
return resultSix lines including the import, and the CFO gets a dashboard-ready export. load_campaigns_from_csv reads the Salesforce dump, campaigns_to_json writes the output. That's a two-function pipeline from raw export to structured handoff.
And the shape stays true to the source data — no information lost, no manual reformatting. One pitfall: json.dumps only accepts JSON-serialisable types. Python datetime objects, sets, and custom class instances raise a TypeError. Keep your dicts to strings, numbers, booleans, and None and you'll never hit that wall.
json.dumps(obj, indent=2) converts any JSON-serialisable Python object to a formatted string. json.loads(text) reverses it.
| Python | JSON |
|---|---|
True / False | true / false |
None | null |
str, int, float | same |
dumps vs dump — dumps returns a string; dump writes to a file object.indent omitted — output is one dense line, unreadable by humans.TypeError at runtime; keep dicts to primitive types.Riley's CFO wants the week's campaign data exported as a formatted JSON string so the BI team can load it into their dashboard config. Write `campaigns_to_json(campaigns)` that takes a list of campaign dicts (each with `"name"`, `"channel"`, `"spend"`, `"leads"`, and `"active"` keys) and returns a JSON-formatted string using `json.dumps` with `indent=2`. Python booleans become `true`/`false` and `None` becomes `null` in the output.
Tap each step for scaffolded hints.
No blank-editor panic.