diff --git a/google/cloud/bigquery/_helpers.py b/google/cloud/bigquery/_helpers.py index 2310224ae..47851d42c 100644 --- a/google/cloud/bigquery/_helpers.py +++ b/google/cloud/bigquery/_helpers.py @@ -19,6 +19,7 @@ import datetime import decimal import re +import six from google.cloud._helpers import UTC from google.cloud._helpers import _date_from_iso8601_date @@ -447,15 +448,16 @@ def _record_field_to_json(fields, row_value): if isdict: processed_fields.add(subname) - # Unknown fields should not be silently dropped. + # Unknown fields should not be silently dropped, include them. Since there + # is no schema information available for them, include them as strings + # to make them JSON-serializable. if isdict: not_processed = set(row_value.keys()) - processed_fields - if not_processed: - raise ValueError( - "Unknown field(s) not present in schema: {}".format( - ", ".join(not_processed) - ) - ) + + for field_name in not_processed: + value = row_value[field_name] + if value is not None: + record[field_name] = six.text_type(value) return record diff --git a/tests/unit/test__helpers.py b/tests/unit/test__helpers.py index 4dd4a8520..c29bedd7b 100644 --- a/tests/unit/test__helpers.py +++ b/tests/unit/test__helpers.py @@ -916,10 +916,14 @@ def test_w_dict_unknown_fields(self): _make_field("INT64", name="one", mode="NULLABLE"), _make_field("STRING", name="two", mode="NULLABLE"), ] - original = {"whoami": "_?_?_", "one": 111, "two": "222"} + original = {"whoami": datetime.date(2020, 7, 20), "one": 111, "two": "222"} - with six.assertRaisesRegex(self, ValueError, r".*[Uu]nknown field.*whoami.*"): - self._call_fut(fields, original) + converted = self._call_fut(fields, original) + + # Unknown fields should be included, but converted as strings. + self.assertEqual( + converted, {"whoami": "2020-07-20", "one": "111", "two": "222"}, + ) class Test_field_to_json(unittest.TestCase):