Skip to content

json

json.loads() - Deserialize JSON string to Python object.

json.dumps() - Serialize Python object to JSON string.

JSON round-trip: dumps → loads should preserve data.

JSON edge cases and quirks.

json.load() - Deserialize from file object.

json.dump() - Serialize to file object.

Basic: Parse simple JSON types.

def test_loads_basic_types(self):
    """Basic: Parse simple JSON types."""
    assert json.loads('null') is None
    assert json.loads('true') is True
    assert json.loads('false') is False
    assert json.loads('42') == 42
    assert json.loads('3.14') == 3.14
    assert json.loads('"hello"') == 'hello'

Verification: ✅ Tested in CI

Basic: Parse JSON array to Python list.

def test_loads_array(self):
    """Basic: Parse JSON array to Python list."""
    result = json.loads('[1, 2, 3]')
    assert result == [1, 2, 3]
    assert isinstance(result, list)

Verification: ✅ Tested in CI

Basic: Parse JSON object to Python dict.

def test_loads_object(self):
    """Basic: Parse JSON object to Python dict."""
    result = json.loads('{"name": "Alice", "age": 30}')
    assert result == {'name': 'Alice', 'age': 30}
    assert isinstance(result, dict)

Verification: ✅ Tested in CI

Property: Nested structures are preserved.

def test_loads_nested_structure(self):
    """Property: Nested structures are preserved."""
    json_str = '{"users": [{"name": "Alice"}, {"name": "Bob"}]}'
    result = json.loads(json_str)
    assert len(result['users']) == 2
    assert result['users'][0]['name'] == 'Alice'

Verification: ✅ Tested in CI

Edge: Empty arrays and objects.

def test_loads_empty_structures(self):
    """Edge: Empty arrays and objects."""
    assert json.loads('[]') == []
    assert json.loads('{}') == {}

Verification: ✅ Tested in CI

Edge: Unicode characters are handled.

def test_loads_unicode(self):
    """Edge: Unicode characters are handled."""
    result = json.loads('{"emoji": "\\u2764"}')
    assert result == {'emoji': '❤'}

Verification: ✅ Tested in CI

Error: Invalid JSON raises JSONDecodeError.

def test_loads_invalid_json_raises(self):
    """Error: Invalid JSON raises JSONDecodeError."""
    with pytest.raises(json.JSONDecodeError):
        json.loads('{invalid}')
    with pytest.raises(json.JSONDecodeError):
        json.loads('[1, 2,]')

Verification: ✅ Tested in CI

Edge: Duplicate keys - last value wins.

def test_loads_strict_duplicate_keys(self):
    """Edge: Duplicate keys - last value wins."""
    result = json.loads('{"key": 1, "key": 2}')
    assert result == {'key': 2}

Verification: ✅ Tested in CI

Basic: Serialize simple Python types.

def test_dumps_basic_types(self):
    """Basic: Serialize simple Python types."""
    assert json.dumps(None) == 'null'
    assert json.dumps(True) == 'true'
    assert json.dumps(False) == 'false'
    assert json.dumps(42) == '42'
    assert json.dumps('hello') == '"hello"'

Verification: ✅ Tested in CI

Basic: Serialize Python list to JSON array.

def test_dumps_list(self):
    """Basic: Serialize Python list to JSON array."""
    result = json.dumps([1, 2, 3])
    assert result == '[1, 2, 3]'

Verification: ✅ Tested in CI

Basic: Serialize Python dict to JSON object.

def test_dumps_dict(self):
    """Basic: Serialize Python dict to JSON object."""
    result = json.dumps({'name': 'Alice'})
    assert json.loads(result) == {'name': 'Alice'}

Verification: ✅ Tested in CI

Property: Nested structures are serialized correctly.

def test_dumps_nested_structure(self):
    """Property: Nested structures are serialized correctly."""
    data = {'users': [{'name': 'Alice'}, {'name': 'Bob'}]}
    result = json.dumps(data)
    assert json.loads(result) == data

Verification: ✅ Tested in CI

Feature: Pretty-printing with indent.

def test_dumps_with_indent(self):
    """Feature: Pretty-printing with indent."""
    data = {'name': 'Alice', 'age': 30}
    result = json.dumps(data, indent=2)
    assert '\n' in result
    assert '  ' in result

Verification: ✅ Tested in CI

Feature: ASCII encoding option.

def test_dumps_ensure_ascii(self):
    """Feature: ASCII encoding option."""
    data = {'emoji': '❤'}
    result_ascii = json.dumps(data, ensure_ascii=True)
    assert '\\u' in result_ascii
    result_unicode = json.dumps(data, ensure_ascii=False)
    assert '❤' in result_unicode

Verification: ✅ Tested in CI

Feature: Deterministic ordering with sort_keys.

def test_dumps_sort_keys(self):
    """Feature: Deterministic ordering with sort_keys."""
    data = {'z': 1, 'a': 2, 'm': 3}
    result = json.dumps(data, sort_keys=True)
    assert result == '{"a": 2, "m": 3, "z": 1}'

Verification: ✅ Tested in CI

Error: Non-serializable types raise TypeError.

def test_dumps_non_serializable_raises(self):
    """Error: Non-serializable types raise TypeError."""
    with pytest.raises(TypeError):
        json.dumps(set([1, 2, 3]))
    with pytest.raises(TypeError):
        json.dumps(complex(1, 2))

Verification: ✅ Tested in CI

Feature: Custom separators for compact output.

def test_dumps_custom_separators(self):
    """Feature: Custom separators for compact output."""
    data = {'a': 1, 'b': 2}
    compact = json.dumps(data, separators=(',', ':'))
    assert ', ' not in compact
    assert ': ' not in compact

Verification: ✅ Tested in CI

Property: dumps → loads round-trip preserves data.

@given(st.one_of(st.none(), st.booleans(), st.integers(), st.floats(allow_nan=False, allow_infinity=False), st.text(), st.lists(st.integers(), max_size=10), st.dictionaries(st.text(min_size=1), st.integers(), max_size=10)))
def test_roundtrip_preserves_data(self, value):
    """Property: dumps → loads round-trip preserves data."""
    if isinstance(value, float) and value != value:
        return
    json_str = json.dumps(value)
    result = json.loads(json_str)
    assert result == value

Verification: ✅ Tested in CI

Property: Complex nested structures survive round-trip.

def test_roundtrip_nested_structure(self):
    """Property: Complex nested structures survive round-trip."""
    original = {'users': [{'name': 'Alice', 'scores': [95, 87, 92]}, {'name': 'Bob', 'scores': [88, 91, 85]}], 'metadata': {'version': 1, 'count': 2}}
    json_str = json.dumps(original)
    result = json.loads(json_str)
    assert result == original

Verification: ✅ Tested in CI

Edge: Infinity and NaN are allowed by default (non-standard JSON).

def test_inf_nan_allowed_by_default(self):
    """Edge: Infinity and NaN are allowed by default (non-standard JSON)."""
    result_inf = json.dumps(float('inf'))
    assert result_inf == 'Infinity'
    result_nan = json.dumps(float('nan'))
    assert result_nan == 'NaN'

Verification: ✅ Tested in CI

Edge: allow_nan=False rejects Infinity/NaN (strict JSON).

def test_inf_nan_rejected_with_allow_nan_false(self):
    """Edge: allow_nan=False rejects Infinity/NaN (strict JSON)."""
    with pytest.raises(ValueError):
        json.dumps(float('inf'), allow_nan=False)
    with pytest.raises(ValueError):
        json.dumps(float('nan'), allow_nan=False)

Verification: ✅ Tested in CI

Edge: Leading/trailing whitespace is ignored.

def test_trailing_whitespace_ignored(self):
    """Edge: Leading/trailing whitespace is ignored."""
    assert json.loads('  42  ') == 42
    assert json.loads('\n\t"hello"\n') == 'hello'

Verification: ✅ Tested in CI

Edge: Escape sequences are handled correctly.

def test_escape_sequences(self):
    """Edge: Escape sequences are handled correctly."""
    assert json.loads('"line1\\nline2"') == 'line1\nline2'
    assert json.loads('"col1\\tcol2"') == 'col1\tcol2'
    assert json.loads('"path\\\\file"') == 'path\\file'

Verification: ✅ Tested in CI

Edge: Large integers are preserved exactly.

def test_large_numbers_preserved(self):
    """Edge: Large integers are preserved exactly."""
    large_num = 123456789012345678901234567890
    json_str = json.dumps(large_num)
    result = json.loads(json_str)
    assert result == large_num

Verification: ✅ Tested in CI

Edge: Floating point precision limitations.

def test_float_precision_quirks(self):
    """Edge: Floating point precision limitations."""
    original = 0.1 + 0.2
    json_str = json.dumps(original)
    result = json.loads(json_str)
    assert abs(result - 0.3) < 0.0001

Verification: ✅ Tested in CI

Basic: Load JSON from file.

def test_load_from_file(self, tmp_path):
    """Basic: Load JSON from file."""
    json_file = tmp_path / 'data.json'
    json_file.write_text('{"name": "Alice", "age": 30}')
    with open(json_file) as f:
        result = json.load(f)
    assert result == {'name': 'Alice', 'age': 30}

Verification: ✅ Tested in CI

Basic: Dump JSON to file.

def test_dump_to_file(self, tmp_path):
    """Basic: Dump JSON to file."""
    json_file = tmp_path / 'output.json'
    data = {'name': 'Bob', 'scores': [85, 90, 88]}
    with open(json_file, 'w') as f:
        json.dump(data, f)
    content = json_file.read_text()
    assert json.loads(content) == data

Verification: ✅ Tested in CI