fix: use pessimistic json encoder in SQL Lab (#28266)
This commit is contained in:
parent
d1e13ab3e4
commit
c10cee3a39
|
|
@ -340,15 +340,15 @@ class SqlLabRestApi(BaseSupersetApi):
|
||||||
key = params.get("key")
|
key = params.get("key")
|
||||||
rows = params.get("rows")
|
rows = params.get("rows")
|
||||||
result = SqlExecutionResultsCommand(key=key, rows=rows).run()
|
result = SqlExecutionResultsCommand(key=key, rows=rows).run()
|
||||||
# return the result without special encoding
|
|
||||||
return json_success(
|
# Using pessimistic json serialization since some database drivers can return
|
||||||
json.dumps(
|
# unserializeable types at times
|
||||||
result,
|
payload = json.dumps(
|
||||||
default=utils.json_iso_dttm_ser,
|
result,
|
||||||
ignore_nan=True,
|
default=utils.pessimistic_json_iso_dttm_ser,
|
||||||
),
|
ignore_nan=True,
|
||||||
200,
|
|
||||||
)
|
)
|
||||||
|
return json_success(payload, 200)
|
||||||
|
|
||||||
@expose("/execute/", methods=("POST",))
|
@expose("/execute/", methods=("POST",))
|
||||||
@protect()
|
@protect()
|
||||||
|
|
|
||||||
|
|
@ -507,8 +507,8 @@ def json_iso_dttm_ser(obj: Any, pessimistic: bool = False) -> Any:
|
||||||
return base_json_conv(obj)
|
return base_json_conv(obj)
|
||||||
except TypeError as ex:
|
except TypeError as ex:
|
||||||
if pessimistic:
|
if pessimistic:
|
||||||
|
logger.error("Failed to serialize %s", obj)
|
||||||
return f"Unserializable [{type(obj)}]"
|
return f"Unserializable [{type(obj)}]"
|
||||||
|
|
||||||
raise ex
|
raise ex
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@
|
||||||
# KIND, either express or implied. See the License for the
|
# KIND, either express or implied. See the License for the
|
||||||
# specific language governing permissions and limitations
|
# specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
import datetime
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
|
|
@ -31,8 +33,10 @@ from superset.utils.core import (
|
||||||
generic_find_fk_constraint_name,
|
generic_find_fk_constraint_name,
|
||||||
get_datasource_full_name,
|
get_datasource_full_name,
|
||||||
is_test,
|
is_test,
|
||||||
|
json_iso_dttm_ser,
|
||||||
normalize_dttm_col,
|
normalize_dttm_col,
|
||||||
parse_boolean_string,
|
parse_boolean_string,
|
||||||
|
pessimistic_json_iso_dttm_ser,
|
||||||
QueryObjectFilterClause,
|
QueryObjectFilterClause,
|
||||||
remove_extra_adhoc_filters,
|
remove_extra_adhoc_filters,
|
||||||
)
|
)
|
||||||
|
|
@ -396,3 +400,40 @@ def test_get_datasource_full_name():
|
||||||
get_datasource_full_name("db", "table", "catalog", None)
|
get_datasource_full_name("db", "table", "catalog", None)
|
||||||
== "[db].[catalog].[table]"
|
== "[db].[catalog].[table]"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_json_iso_dttm_ser():
|
||||||
|
data = {
|
||||||
|
"datetime": datetime.datetime(2021, 1, 1, 0, 0, 0),
|
||||||
|
"date": datetime.date(2021, 1, 1),
|
||||||
|
}
|
||||||
|
json_str = json.dumps(data, default=json_iso_dttm_ser)
|
||||||
|
reloaded_data = json.loads(json_str)
|
||||||
|
assert reloaded_data["datetime"] == "2021-01-01T00:00:00"
|
||||||
|
assert reloaded_data["date"] == "2021-01-01"
|
||||||
|
|
||||||
|
|
||||||
|
def test_pessimistic_json_iso_dttm_ser():
|
||||||
|
data = {
|
||||||
|
"datetime": datetime.datetime(2021, 1, 1, 0, 0, 0),
|
||||||
|
"date": datetime.date(2021, 1, 1),
|
||||||
|
"UNSERIALIZABLE": MagicMock(),
|
||||||
|
}
|
||||||
|
json_str = json.dumps(data, default=pessimistic_json_iso_dttm_ser)
|
||||||
|
reloaded_data = json.loads(json_str)
|
||||||
|
assert reloaded_data["datetime"] == "2021-01-01T00:00:00"
|
||||||
|
assert reloaded_data["date"] == "2021-01-01"
|
||||||
|
assert (
|
||||||
|
reloaded_data["UNSERIALIZABLE"]
|
||||||
|
== "Unserializable [<class 'unittest.mock.MagicMock'>]"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_pessimistic_json_iso_dttm_ser_nonutf8():
|
||||||
|
data = {
|
||||||
|
"INVALID_UTF8_BYTES": b"\xff",
|
||||||
|
}
|
||||||
|
assert isinstance(data["INVALID_UTF8_BYTES"], bytes)
|
||||||
|
json_str = json.dumps(data, default=pessimistic_json_iso_dttm_ser)
|
||||||
|
reloaded_data = json.loads(json_str)
|
||||||
|
assert reloaded_data["INVALID_UTF8_BYTES"] == "[bytes]"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue