snowflakedb / snowpark-java-scala

Snowflake Snowpark Java & Scala API
Apache License 2.0
18 stars 20 forks source link

SNOW-1348543: Variant.asJsonString() produces invalid JSON when array contains null values #103

Open ehclark opened 4 months ago

ehclark commented 4 months ago

The Variant.asJsonString() outputs undefined for null values instead of null.

The following test:

import java.io.FileInputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.junit.jupiter.api.Test;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.snowflake.snowpark_java.Row;
import com.snowflake.snowpark_java.Session;
import com.snowflake.snowpark_java.types.Variant;

public class TestNullArray {
    @Test
    public void testArray() throws Exception {

        Map<String, String> sfConnProps = new HashMap<>();
        try (FileInputStream in = new FileInputStream("sf-conn.properties")) {
            Properties props = new Properties();
            props.load(in);
            props.forEach((key, value) -> sfConnProps.put((String) key, (String) value));
        }
        Session sess = null;
        try {
            sess = Session.builder().configs(sfConnProps).create();

            sess.sql("CREATE TEMPORARY TABLE test_array (array_col ARRAY)").count();
            sess.sql("INSERT INTO test_array SELECT ARRAY_CONSTRUCT('one', 'two')").count();
            sess.sql("INSERT INTO test_array SELECT ARRAY_CONSTRUCT(NULL, 'two')").count();
            Row[] rows = sess.sql("SELECT * FROM test_array").collect();
            for (int i = 0; i < rows.length; i++)
            {
                Variant value = rows[i].getVariant(0);
                String valueJson = value.asJsonString();
                String[] array = new ObjectMapper().readValue(valueJson, String[].class);
            }
        } finally {
            sess.close();
        }
    }
}

Produces the following error:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `java.lang.String[]`: no String-argument constructor/factory method to deserialize from String value ('[
  undefined,
  "two"
]')
 at [Source: (String)""[\n  undefined,\n  \"two\"\n]""; line: 1, column: 1]
 at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from([InvalidDefinitionException.java:67](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
 at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition([DeserializationContext.java:1904](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
 at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition([DatabindContext.java:400](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
 at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator([DeserializationContext.java:1344](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
 at com.fasterxml.jackson.databind.deser.std.StdDeserializer._deserializeFromString([StdDeserializer.java:311](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
 at com.fasterxml.jackson.databind.deser.std.StringArrayDeserializer.handleNonArray([StringArrayDeserializer.java:317](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
 at com.fasterxml.jackson.databind.deser.std.StringArrayDeserializer.deserialize([StringArrayDeserializer.java:141](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
 at com.fasterxml.jackson.databind.deser.std.StringArrayDeserializer.deserialize([StringArrayDeserializer.java:25](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
 at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue([DefaultDeserializationContext.java:323](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
 at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose([ObjectMapper.java:4674](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
 at com.fasterxml.jackson.databind.ObjectMapper.readValue([ObjectMapper.java:3629](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
 at com.fasterxml.jackson.databind.ObjectMapper.readValue([ObjectMapper.java:3597](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
 at org.mgb.pm.gdh.extract.vcf.TestNullArray.testArray([TestNullArray.java:35](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
 at java.base/java.util.ArrayList.forEach([ArrayList.java:1541](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))
 at java.base/java.util.ArrayList.forEach([ArrayList.java:1541](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html))