Skip to content

Commit 02a7d12

Browse files
tswastkiraksi
andauthored
feat: support JSON type in insert_rows and as a scalar query parameter (#1757)
Co-authored-by: Kira <[email protected]>
1 parent b9c8be0 commit 02a7d12

File tree

4 files changed

+42
-2
lines changed

4 files changed

+42
-2
lines changed

google/cloud/bigquery/_helpers.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,13 @@ def _bytes_to_json(value):
374374
return value
375375

376376

377+
def _json_to_json(value):
378+
"""Coerce 'value' to a BigQuery REST API representation."""
379+
if value is None:
380+
return None
381+
return json.dumps(value)
382+
383+
377384
def _timestamp_to_json_parameter(value):
378385
"""Coerce 'value' to an JSON-compatible representation.
379386
@@ -439,7 +446,7 @@ def _time_to_json(value):
439446
"DATETIME": _datetime_to_json,
440447
"DATE": _date_to_json,
441448
"TIME": _time_to_json,
442-
"JSON": _json_from_json,
449+
"JSON": _json_to_json,
443450
# Make sure DECIMAL and BIGDECIMAL are handled, even though
444451
# requests for them should be converted to NUMERIC. Better safe
445452
# than sorry.

tests/system/test_client.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -2049,13 +2049,18 @@ def test_insert_rows_nested_nested(self):
20492049
),
20502050
],
20512051
),
2052+
SF("json_col", "JSON"),
20522053
]
20532054
record = {
20542055
"nested_string": "another string value",
20552056
"nested_repeated": [0, 1, 2],
20562057
"nested_record": {"nested_nested_string": "some deep insight"},
20572058
}
2058-
to_insert = [("Some value", record)]
2059+
json_record = {
2060+
"json_array": [1, 2, 3],
2061+
"json_object": {"alpha": "abc", "num": 123},
2062+
}
2063+
to_insert = [("Some value", record, json_record)]
20592064
table_id = "test_table"
20602065
dataset = self.temp_dataset(_make_dataset_id("issue_2951"))
20612066
table_arg = Table(dataset.table(table_id), schema=schema)

tests/system/test_query.py

+12
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,18 @@ def test_query_statistics(bigquery_client, query_api_method):
256256
)
257257
],
258258
),
259+
pytest.param(
260+
"SELECT @json",
261+
{"alpha": "abc", "num": [1, 2, 3]},
262+
[
263+
ScalarQueryParameter(
264+
name="json",
265+
type_="JSON",
266+
value={"alpha": "abc", "num": [1, 2, 3]},
267+
)
268+
],
269+
id="scalar-json",
270+
),
259271
(
260272
"SELECT @naive_time",
261273
datetime.time(12, 41, 9, 62500),

tests/unit/test__helpers.py

+16
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,16 @@ def test_w_known_field_type(self):
886886
converted = self._call_fut(field, original)
887887
self.assertEqual(converted, str(original))
888888

889+
def test_w_scalar_none(self):
890+
import google.cloud.bigquery._helpers as module_under_test
891+
892+
scalar_types = module_under_test._SCALAR_VALUE_TO_JSON_ROW.keys()
893+
for type_ in scalar_types:
894+
field = _make_field(type_)
895+
original = None
896+
converted = self._call_fut(field, original)
897+
self.assertIsNone(converted, msg=f"{type_} did not return None")
898+
889899

890900
class Test_single_field_to_json(unittest.TestCase):
891901
def _call_fut(self, field, value):
@@ -921,6 +931,12 @@ def test_w_scalar_ignores_mode(self):
921931
converted = self._call_fut(field, original)
922932
self.assertEqual(converted, original)
923933

934+
def test_w_scalar_json(self):
935+
field = _make_field("JSON")
936+
original = {"alpha": "abc", "num": [1, 2, 3]}
937+
converted = self._call_fut(field, original)
938+
self.assertEqual(converted, json.dumps(original))
939+
924940

925941
class Test_repeated_field_to_json(unittest.TestCase):
926942
def _call_fut(self, field, value):

0 commit comments

Comments
 (0)