Skip to content

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

Learn how to serialize Python lists of dictionaries to strings using json.dumps(), custom formatting, and handling complex types like datetime and Decimal for APIs, logs, and debugging.

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'>

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 = json.dumps(data, separators=(',', ':'))
print(f"Compact:  {compact}")

sorted_str = json.dumps(data, sort_keys=True)
print(f"Sorted:   {sorted_str}")

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}]

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}]

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}
]

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

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

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(2024, 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": "2024-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(2024, 1, 15, 10, 30), "value": 42}]
json_str = json.dumps(data, default=serialize_custom)
print(json_str)

Output:

[{"timestamp": "2024-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}]

Method Comparison

Method Output Format Parseable By Other Languages Use Case
json.dumps() [{"k": "v"}] Yes APIs, storage, data interchange
json.dumps(indent=2) Pretty JSON Yes Logs, debugging, config files
str() [{'k': 'v'}] No Quick Python debugging only
Custom formatting Any format Depends Reports, 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.

Navigation