From e85db191bc2c8d05dce6a4cd67df8243ba11b54a Mon Sep 17 00:00:00 2001 From: Ben Theunissen Date: Tue, 21 Nov 2023 16:26:36 -0500 Subject: [PATCH] Fix conversion (#76) * Force fix * Force fix * Only do decimalc * Fix * Fix --- pyproject.toml | 2 +- target_clickhouse/sinks.py | 28 +++++++++++++++++++++++++--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1c7c430..2b28861 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "shaped-target-clickhouse" -version = "0.1.8" +version = "0.1.9" description = "`target-clickhouse` is a Singer target for clickhouse, built with the Meltano Singer SDK." readme = "README.md" authors = ["Ben Theunissen"] diff --git a/target_clickhouse/sinks.py b/target_clickhouse/sinks.py index 4f93d07..f3e30dd 100644 --- a/target_clickhouse/sinks.py +++ b/target_clickhouse/sinks.py @@ -2,6 +2,8 @@ from __future__ import annotations +import decimal +from collections.abc import MutableMapping from typing import Any, Iterable import jsonschema.exceptions as jsonschema_exceptions @@ -173,10 +175,10 @@ def _pre_validate_for_string_type(self, record: dict) -> dict: for key, value in record.items(): # Checking if the schema expects a string for this key. expected_type = self.schema.get("properties", {}).get(key, {}).get("type") - if expected_type == "string" and not isinstance(value, str): + if "string" in expected_type and not isinstance(value, str): # Convert the value to string if it's not already a string. record[key] = ( - json.dumps(value) + json.dumps(record[key]) if isinstance(value, (dict, list)) else str(value) ) if self.logger: @@ -184,4 +186,24 @@ def _pre_validate_for_string_type(self, record: dict) -> dict: f"Converted field {key} to string: {record[key]}", ) - return record + return self._convert_decimal_to_float(record) + + def _convert_decimal_to_float(self, obj): + """Recursively convert all Decimal values in a dictionary to floats. + + Args: + obj: The input object (dictionary, list, or any other data type). + + Returns: + The object with all Decimal values converted to strings. + """ + if isinstance(obj, MutableMapping): + for key, value in obj.items(): + obj[key] = self._convert_decimal_to_float(value) + elif isinstance(obj, list): + for i, item in enumerate(obj): + obj[i] = self._convert_decimal_to_float(item) + elif isinstance(obj, decimal.Decimal): + return float(obj) + + return obj