Skip to main content

How to Convert a List of Dictionaries to a String in Python

Serializing lists of dictionaries to strings is essential for saving data to files, logging, API transmission, and debugging. The approach you choose depends on whether you need a standardized interchange format, a human-readable display, or a custom output layout.

In this guide, you will learn multiple methods to convert lists of dictionaries into strings, handle complex data types that are not natively serializable, and choose the right format for your use case.

The json module produces standardized JSON strings that are compatible with JavaScript, web APIs, and virtually all programming languages:

import json

data = [
{"id": 1, "name": "Alice", "active": True},
{"id": 2, "name": "Bob", "active": None}
]

json_str = json.dumps(data)

print(json_str)
print(type(json_str))

Output:

[{"id": 1, "name": "Alice", "active": true}, {"id": 2, "name": "Bob", "active": null}]
<class 'str'>
Automatic Type Conversions

JSON serialization automatically converts Python-specific types to their JSON equivalents:

  • True / False become true / false
  • None becomes null
  • Tuples become JSON arrays

Pretty Printing for Readability

For configuration files, logs, or any context where humans need to read the output, use the indent parameter:

import json

data = [
{"id": 1, "name": "Alice"},
{"id": 2, "name": "Bob"}
]

pretty_str = json.dumps(data, indent=2)
print(pretty_str)

Output:

[
{
"id": 1,
"name": "Alice"
},
{
"id": 2,
"name": "Bob"
}
]

Additional Formatting Options

The json.dumps() function provides several parameters for controlling the output:

import json

data = [{"name": "Müller", "score": 95.5}]

# Compact output with no spaces
compact = json.dumps(data, separators=(',', ':'))
print(f"Compact: {compact}")

# Sorted keys for consistent, reproducible output
sorted_str = json.dumps(data, sort_keys=True)
print(f"Sorted: {sorted_str}")

# Escape non-ASCII characters
ascii_str = json.dumps(data, ensure_ascii=True)
print(f"ASCII: {ascii_str}")

Output:

Compact:  [{"name":"M\u00fcller","score":95.5}]
Sorted: [{"name": "M\u00fcller", "score": 95.5}]
ASCII: [{"name": "M\u00fcller", "score": 95.5}]

The compact format is useful for minimizing payload size in API responses, while sort_keys=True ensures that the same data always produces identical output, which is helpful for caching and testing.

Using str() (Python Representation)

Casting to str() produces a string that uses Python syntax rather than JSON:

data = [{"val": 10, "active": True, "name": None}]

s = str(data)
print(s)

Output:

[{'val': 10, 'active': True, 'name': None}]
Not Interchangeable with JSON

The output of str() uses single quotes and Python-specific literals (True, None, False). This output will fail when parsed by JavaScript, other languages, or even Python's own json.loads(). Use str() only for quick debugging within a Python environment.

import json

python_str = str([{"active": True}])
print(python_str) # [{'active': True}]

# This fails because it's not valid JSON
try:
json.loads(python_str)
except json.JSONDecodeError as e:
print(f"Error: {e}")

Output:

[{'active': True}]
Error: Expecting property name enclosed in double quotes: line 1 column 3 (char 2)

Using repr() for Debugging

The repr() function is similar to str() but explicitly shows escape sequences, which can be helpful when debugging strings that contain special characters:

data = [{"text": "Hello\nWorld"}]

print(str(data))
print(repr(data))

Output:

[{'text': 'Hello\nWorld'}]
[{'text': 'Hello\nWorld'}]

Custom String Formatting

For specific output formats like logs, reports, or display strings, use f-strings and join():

users = [
{"name": "Alice", "role": "admin", "score": 95},
{"name": "Bob", "role": "user", "score": 87}
]

# Inline summary format
formatted = " | ".join(f"{u['name']}({u['role']})" for u in users)
print(formatted)

# Table-like format
print(f"\n{'Name':<12} {'Role':<10} {'Score'}")
print("-" * 30)
for u in users:
print(f"{u['name']:<12} {u['role']:<10} {u['score']}")

Output:

Alice(admin) | Bob(user)

Name Role Score
------------------------------
Alice admin 95
Bob user 87

Creating a CSV-Like String

users = [
{"id": 1, "name": "Alice", "email": "alice@example.com"},
{"id": 2, "name": "Bob", "email": "bob@example.com"}
]

headers = list(users[0].keys())
header_line = ",".join(headers)
data_lines = [",".join(str(u[h]) for h in headers) for u in users]

csv_str = header_line + "\n" + "\n".join(data_lines)
print(csv_str)

Output:

id,name,email
1,Alice,alice@example.com
2,Bob,bob@example.com
note

For production CSV generation, use Python's built-in csv module instead of manual string joining. It correctly handles edge cases like values that contain commas, quotes, or newlines.

Handling Complex Data Types

The json module cannot serialize all Python types out of the box. Attempting to serialize objects like datetime, Decimal, or set raises a TypeError:

import json
from datetime import datetime
from decimal import Decimal

data = [
{
"date": datetime.now(),
"amount": Decimal("19.99"),
"items": {1, 2, 3}
}
]

try:
json.dumps(data)
except TypeError as e:
print(f"Error: {e}")

Output:

Error: Object of type datetime is not JSON serializable

Solution: Custom JSON Encoder

Create a custom encoder class to define how non-standard types should be serialized:

import json
from datetime import datetime, date
from decimal import Decimal

class CustomEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, (datetime, date)):
return obj.isoformat()
if isinstance(obj, Decimal):
return float(obj)
if isinstance(obj, set):
return sorted(list(obj))
return super().default(obj)

data = [
{
"date": datetime(2026, 7, 15, 10, 30),
"amount": Decimal("19.99"),
"items": {3, 1, 2}
}
]

json_str = json.dumps(data, cls=CustomEncoder, indent=2)
print(json_str)

Output:

[
{
"date": "2026-07-15T10:30:00",
"amount": 19.99,
"items": [1, 2, 3]
}
]

Using the default Parameter for Simple Cases

For quick, inline handling without defining a full class, pass a function to the default parameter:

import json
from datetime import datetime

def serialize_custom(obj):
"""Handle non-serializable types."""
if hasattr(obj, 'isoformat'):
return obj.isoformat()
if hasattr(obj, '__dict__'):
return obj.__dict__
raise TypeError(f"Object of type {type(obj).__name__} is not JSON serializable")

data = [{"timestamp": datetime(2026, 1, 15, 10, 30), "value": 42}]
json_str = json.dumps(data, default=serialize_custom)
print(json_str)

Output:

[{"timestamp": "2026-01-15T10:30:00", "value": 42}]

Formatting for Log Files

When writing structured log entries, a compact JSON representation per line is often the best approach:

import json

def format_for_log(records):
"""Format a list of dicts as individual compact JSON log lines."""
lines = []
for i, record in enumerate(records):
json_line = json.dumps(record, separators=(',', ':'))
lines.append(f"Record {i}: {json_line}")
return "\n".join(lines)

data = [
{"event": "login", "user": "alice"},
{"event": "purchase", "amount": 99.99}
]

print(format_for_log(data))

Output:

Record 0: {"event":"login","user":"alice"}
Record 1: {"event":"purchase","amount":99.99}

Converting a String Back to a List of Dictionaries

From a JSON String

import json

json_str = '[{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]'
data = json.loads(json_str)

print(data)
print(type(data[0]))

Output:

[{'id': 1, 'name': 'Alice'}, {'id': 2, 'name': 'Bob'}]
<class 'dict'>

From a Python repr String

If you have a string produced by str() or repr(), use ast.literal_eval() to parse it safely:

import ast

python_str = "[{'id': 1, 'active': True}, {'id': 2, 'active': False}]"
data = ast.literal_eval(python_str)
print(data)

Output:

[{'id': 1, 'active': True}, {'id': 2, 'active': False}]
Security Warning

Never use eval() on untrusted strings. It executes arbitrary Python code, which is a serious security vulnerability. Use ast.literal_eval(), which only evaluates literal values like strings, numbers, tuples, lists, dicts, booleans, and None. For data interchange, always prefer JSON format with json.loads().

Method Comparison

MethodOutput FormatParseable By Other LanguagesUse Case
json.dumps()[{"k": "v"}]YesAPIs, storage, data interchange
json.dumps(indent=2)Pretty JSONYesLogs, debugging, config files
str()[{'k': 'v'}]NoQuick Python debugging only
Custom formattingAny formatDependsReports, displays, log entries

Conclusion

For any situation where the serialized string will be stored, transmitted, or consumed by other systems, json.dumps() is the standard and recommended choice. It produces universally parseable output and provides fine-grained control over formatting through parameters like indent, sort_keys, and separators. For complex Python types that JSON cannot serialize natively, use a custom encoder class or the default parameter to define conversion rules.

Best Practice

Always use json.dumps() for data that will be stored, transmitted, or shared between systems. It produces standardized output that any language can parse. Reserve str() and repr() only for quick debugging prints where the output will not leave your Python environment.