Decode JSON columns without changing table row values

Refs #3003
This commit is contained in:
IlyaKhalafi 2026-10-14 11:33:12 +00:00
commit a91e56d529
2 changed files with 119 additions and 18 deletions

View file

@ -775,6 +775,95 @@ test_json_columns_default_expected = [
]
@pytest.mark.asyncio
@pytest.mark.parametrize("endpoint", ["table", "query"])
@pytest.mark.parametrize("include_columns", [False, True])
@pytest.mark.parametrize(
"shape", ["objects", "object", "array", "arrayfirst", "arrays"]
)
async def test_json_columns_with_output_shapes(endpoint, include_columns, shape):
if endpoint == "query" and shape == "object":
pytest.skip("Object shape requires a table primary key")
ds = Datasette()
db = ds.add_memory_database("json_shapes")
await db.execute_write("CREATE TABLE t (value text, id integer primary key)")
await db.execute_write("INSERT INTO t VALUES (?, ?)", ['["a", "b"]', 1])
parameters = {"_json": "value", "_shape": shape}
if include_columns:
parameters["_extra"] = "columns"
if endpoint == "query":
parameters["sql"] = "SELECT value, id FROM t"
path = "/json_shapes/-/query.json"
else:
path = "/json_shapes/t.json"
try:
response = await ds.client.get(path + "?" + urllib.parse.urlencode(parameters))
assert response.status_code == 200
result = response.json()
row = {"value": ["a", "b"], "id": 1}
if shape == "object":
assert result == {"1": row}
elif shape == "array":
assert result == [row]
elif shape == "arrayfirst":
assert result == [["a", "b"]]
elif shape == "arrays":
assert result["rows"] == [[["a", "b"], 1]]
else:
assert result["rows"] == [row]
if shape in ("objects", "arrays"):
assert ("columns" in result) == include_columns
finally:
ds.close()
@pytest.mark.asyncio
@pytest.mark.parametrize("endpoint", ["table", "row"])
@pytest.mark.parametrize(
"value,expected", [('["a"]', ["a"]), ("not JSON", "not JSON"), (None, None)]
)
async def test_json_columns_preserve_other_values(endpoint, value, expected):
ds = Datasette()
db = ds.add_memory_database("json_values")
await db.execute_write(
"CREATE TABLE t (id integer primary key, value text, other text)"
)
await db.execute_write(
"INSERT INTO t VALUES (?, ?, ?)", [1, value, '{"keep": true}']
)
path = "/json_values/t.json" if endpoint == "table" else "/json_values/t/1.json"
try:
response = await ds.client.get(path + "?_json=value")
assert response.status_code == 200
assert response.json()["rows"] == [
{"id": 1, "value": expected, "other": '{"keep": true}'}
]
finally:
ds.close()
@pytest.mark.asyncio
@pytest.mark.parametrize(
"shape", ["objects", "object", "array", "arrayfirst", "arrays"]
)
async def test_json_columns_with_empty_results(shape):
ds = Datasette()
db = ds.add_memory_database("json_empty")
await db.execute_write("CREATE TABLE t (id integer primary key, value text)")
try:
response = await ds.client.get(f"/json_empty/t.json?_json=value&_shape={shape}")
assert response.status_code == 200
result = response.json()
if shape == "object":
assert result == {}
elif shape in ("array", "arrayfirst"):
assert result == []
else:
assert result["rows"] == []
finally:
ds.close()
@pytest.mark.asyncio
@pytest.mark.parametrize(
"extra_args,expected",