Skip to content

Commit 0db1f0e

Browse files
committed
Test JSON scalar to df
1 parent 5e2d713 commit 0db1f0e

1 file changed

Lines changed: 80 additions & 0 deletions

File tree

test/test_json.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,3 +155,83 @@ def test_to_json_python_param_with_homogeneous_list_uses_typed_binding(
155155

156156
assert normalized_query == query
157157
assert normalized_parameters == parameters
158+
159+
160+
def test_get_as_df_json_scalar(conn_db_empty: ConnDB) -> None:
161+
"""Scalar JSON values convert through get_as_df() as Python strings.
162+
163+
Covers non-null values, typed JSON nulls, and a mixed column in a single query.
164+
"""
165+
conn, _ = conn_db_empty
166+
df = conn.execute(
167+
"UNWIND ["
168+
'CAST(\'{"a": 1, "b": [2, 3]}\' AS JSON), '
169+
"CAST(NULL AS JSON), "
170+
"CAST('[1, 2, 3]' AS JSON)"
171+
"] AS j RETURN j"
172+
).get_as_df()
173+
174+
assert str(df["j"].dtype) == "object"
175+
assert df["j"].isna().tolist() == [False, True, False]
176+
177+
first = df["j"].iloc[0]
178+
assert isinstance(first, str)
179+
assert json.loads(first) == {"a": 1, "b": [2, 3]}
180+
181+
third = df["j"].iloc[2]
182+
assert isinstance(third, str)
183+
assert json.loads(third) == [1, 2, 3]
184+
185+
186+
def test_get_as_df_json_empty_result(conn_db_empty: ConnDB) -> None:
187+
"""An empty result over a JSON column builds the column without crashing.
188+
189+
convertToArrayType() runs during NPArrayWrapper construction, before any
190+
rows are iterated, so a zero-row JSON result is the minimal reproduction
191+
for the original dtype-selection crash.
192+
"""
193+
conn, _ = conn_db_empty
194+
conn.execute("CREATE NODE TABLE t (id SERIAL PRIMARY KEY, data JSON)")
195+
196+
df = conn.execute("MATCH (n:t) RETURN n.data AS data").get_as_df()
197+
198+
assert len(df) == 0
199+
assert str(df["data"].dtype) == "object"
200+
201+
202+
def test_get_as_df_json_extract(conn_db_empty: ConnDB) -> None:
203+
"""json_extract() produces a scalar JSON result that converts via get_as_df(). """
204+
conn, _ = conn_db_empty
205+
conn.execute("INSTALL json; LOAD json;")
206+
conn.execute("CREATE NODE TABLE t (id SERIAL PRIMARY KEY, data JSON)")
207+
208+
data = {"name": {"first": "Alice", "last": "Smith"}}
209+
conn.execute(
210+
"CREATE (n:t {data: to_json($data)})",
211+
parameters={"data": json.dumps(data)},
212+
)
213+
214+
df = conn.execute("MATCH (n:t) RETURN json_extract(n.data, '$.name') AS name").get_as_df()
215+
216+
assert str(df["name"].dtype) == "object"
217+
val = df["name"].iloc[0]
218+
assert isinstance(val, str)
219+
assert json.loads(val) == {"first": "Alice", "last": "Smith"}
220+
221+
222+
def test_get_as_df_json_list(conn_db_empty: ConnDB) -> None:
223+
""" JSON[] (LIST of JSON) columns keep their existing pandas behavior. """
224+
conn, _ = conn_db_empty
225+
conn.execute("INSTALL json; LOAD json;")
226+
conn.execute("CREATE NODE TABLE t (id SERIAL PRIMARY KEY, data JSON[])")
227+
228+
data = [{"x": 1}, {"x": 2}, {"x": 3}]
229+
conn.execute("CREATE (n:t {data: $d})", parameters={"d": data})
230+
231+
df = conn.execute("MATCH (n:t) RETURN n.data AS data").get_as_df()
232+
233+
assert str(df["data"].dtype) == "object"
234+
val = df["data"].iloc[0]
235+
assert isinstance(val, list)
236+
assert len(val) == 3
237+
assert all(isinstance(e, str) for e in val)

0 commit comments

Comments
 (0)