Skip to content

Commit 09017a9

Browse files
tomwojcikpartheatswastLinchin
authored
fix: add missing handler for deserializing json value (#1587)
* fix: add missing handler for deserializing json value * fix mypy --------- Co-authored-by: Anthonios Partheniou <[email protected]> Co-authored-by: Tim Swast <[email protected]> Co-authored-by: Lingqing Gan <[email protected]>
1 parent 330fa5e commit 09017a9

File tree

3 files changed

+29
-3
lines changed

3 files changed

+29
-3
lines changed

google/cloud/bigquery/_helpers.py

+8
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import base64
1818
import datetime
1919
import decimal
20+
import json
2021
import math
2122
import re
2223
import os
@@ -412,6 +413,12 @@ def _time_to_json(value):
412413
return value
413414

414415

416+
def _json_from_json(value, field):
417+
"""Coerce 'value' to a pythonic JSON representation, if set or not nullable."""
418+
if _not_null(value, field):
419+
return json.loads(value)
420+
421+
415422
# Converters used for scalar values marshalled as row data.
416423
_SCALAR_VALUE_TO_JSON_ROW = {
417424
"INTEGER": _int_to_json,
@@ -427,6 +434,7 @@ def _time_to_json(value):
427434
"DATETIME": _datetime_to_json,
428435
"DATE": _date_to_json,
429436
"TIME": _time_to_json,
437+
"JSON": _json_from_json,
430438
# Make sure DECIMAL and BIGDECIMAL are handled, even though
431439
# requests for them should be converted to NUMERIC. Better safe
432440
# than sorry.

google/cloud/bigquery/query.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,7 @@ def to_api_repr(self) -> dict:
469469
value = self.value
470470
converter = _SCALAR_VALUE_TO_JSON_PARAM.get(self.type_)
471471
if converter is not None:
472-
value = converter(value)
472+
value = converter(value) # type: ignore
473473
resource: Dict[str, Any] = {
474474
"parameterType": {"type": self.type_},
475475
"parameterValue": {"value": value},
@@ -626,7 +626,7 @@ def to_api_repr(self) -> dict:
626626

627627
converter = _SCALAR_VALUE_TO_JSON_PARAM.get(a_type["type"])
628628
if converter is not None:
629-
values = [converter(value) for value in values]
629+
values = [converter(value) for value in values] # type: ignore
630630
a_values = [{"value": value} for value in values]
631631

632632
resource = {
@@ -775,7 +775,7 @@ def to_api_repr(self) -> dict:
775775
s_types[name] = {"name": name, "type": {"type": type_}}
776776
converter = _SCALAR_VALUE_TO_JSON_PARAM.get(type_)
777777
if converter is not None:
778-
value = converter(value)
778+
value = converter(value) # type: ignore
779779
values[name] = {"value": value}
780780

781781
resource = {

tests/unit/test__helpers.py

+18
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,24 @@ def test_w_float_value(self):
5858
self.assertEqual(coerced, 42)
5959

6060

61+
class Test_json_from_json(unittest.TestCase):
62+
def _call_fut(self, value, field):
63+
from google.cloud.bigquery._helpers import _json_from_json
64+
65+
return _json_from_json(value, field)
66+
67+
def test_w_none_nullable(self):
68+
self.assertIsNone(self._call_fut(None, _Field("NULLABLE")))
69+
70+
def test_w_none_required(self):
71+
with self.assertRaises(TypeError):
72+
self._call_fut(None, _Field("REQUIRED"))
73+
74+
def test_w_string_value(self):
75+
coerced = self._call_fut('{"foo": true}', object())
76+
self.assertEqual(coerced, {"foo": True})
77+
78+
6179
class Test_float_from_json(unittest.TestCase):
6280
def _call_fut(self, value, field):
6381
from google.cloud.bigquery._helpers import _float_from_json

0 commit comments

Comments
 (0)