I am working on a service that pulls VARIANT data from Snowflake and exposes for consumption elsewhere, and I want to prevent the Snowflake connector from escaping and adding string formatting. One approach I am trying is using the converter_class option mentioned here.
Digging in a bit more, I found that the default SnowflakeConverter class doesn't do any action for VARIANT/ARRAY/OBJECT conversion at all: https://github.com/snowflakedb/snowflake-connector-python/blob/79a106ba70355249ea0eff16977bafe774846d90/converter.py#L315. Since that's the case, I extended the class to use this as the _ARRAY_to_python converter (working with just ARRAY for a start):
def convert_array_to_python(self, ctx):
logger.info('trying to convert')
return lambda x: [s.strip('\"\n\t ') for s in x.strip('[\n\t ]').split(',')]
And used conn = connect(user=...., converter_class=CustomConverter()) where CustomConverter looks like this and does something similar to the DefaultConverterClass function here:
def CustomConverterClass():
converter = sf_lib.connection.DefaultConverterClass()
converter._ARRAY_to_python = convert_array_to_python
return converter
I've checked the value of conn.converter_class()._ARRAY_to_python and getattr(conn.converter_class(), '_ARRAY_to_python') after the connection is made, and they both match the convert_array_to_python function defined earlier. And yet, when I execute the query and examine the cursor for the VARIANT column:
cursor = conn.cursor(sf_lib.DictCursor)
data = cursor.execute(query)
for row in data:
...
The values are still escaped. Moreover, it doesn't look like the ARRAY converter is called. I have control over the schema of the table I'm querying, and have confirmed that the column is of type ARRAY.
The Snowflake connector seems to do its json conversion using JsonResult. As far as I can tell digging through the source code, the call stack of the _ARRAY_to_python call should be something like:
next(data)
-> JsonDictResult.__next__()
-> JsonDictResult._row_to_python(row)
-> _convert_ARRAY_to_python(col) (from https://github.com/snowflakedb/snowflake-connector-python/blob/d4f04f20949e2bcb70b0ea0927a8a362ba272389/json_result.py#L178)
Why isn't the converter being called here, and how else can I prevent the json formatting from being applied?