From 117261072c82df6c56e67a25f0eb24f0eb9332cb Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 19 May 2025 13:30:36 -0500 Subject: [PATCH 01/13] add jsonutils --- azure/functions/_cosmosdb.py | 2 +- azure/functions/_jsonutils.py | 71 +++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 azure/functions/_jsonutils.py diff --git a/azure/functions/_cosmosdb.py b/azure/functions/_cosmosdb.py index b9a4de1c..dcdf01c6 100644 --- a/azure/functions/_cosmosdb.py +++ b/azure/functions/_cosmosdb.py @@ -2,9 +2,9 @@ # Licensed under the MIT License. import collections -import json from . import _abc +from ._jsonutils import json class Document(_abc.Document, collections.UserDict): diff --git a/azure/functions/_jsonutils.py b/azure/functions/_jsonutils.py new file mode 100644 index 00000000..3b077f15 --- /dev/null +++ b/azure/functions/_jsonutils.py @@ -0,0 +1,71 @@ +from abc import ABC, abstractmethod +import types + + +class JsonInterface(ABC): + @abstractmethod + def dumps(self, obj) -> str: + pass + + @abstractmethod + def loads(self, s: str): + pass + +class OrJsonAdapter(JsonInterface): + def __init__(self): + import orjson + self.orjson = orjson + + def dumps(self, obj) -> str: + return self.orjson.dumps(obj).decode("utf-8") + + def loads(self, s: str): + return self.orjson.loads(s) + + +class UJsonAdapter(JsonInterface): + def __init__(self): + import ujson + self.ujson = ujson + + def dumps(self, obj) -> str: + return self.ujson.dumps(obj) + + def loads(self, s: str): + return self.ujson.loads(s) + + +class StdJsonAdapter(JsonInterface): + def __init__(self): + import json + self.json = json + + def dumps(self, obj, **kwargs) -> str: + return self.json.dumps(obj, **kwargs) + + def loads(self, s: str): + return self.json.loads(s) + + +json_impl = None +for adapter_cls in (OrJsonAdapter, UJsonAdapter, StdJsonAdapter): + try: + json_impl = adapter_cls() + break + except ImportError: + continue + +def dumps(obj, **kwargs) -> str: + if json_impl is None: + raise ImportError("No JSON adapter found") + return json_impl.dumps(obj, **kwargs) + +def loads(s: str): + if json_impl is None: + raise ImportError("No JSON adapter found") + return json_impl.loads(s) + +json = types.SimpleNamespace( + dumps=dumps, + loads=loads +) From f9ee328e721b07977f6ed8c3327567faf941d4cd Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 19 May 2025 14:10:59 -0500 Subject: [PATCH 02/13] formatting --- azure/functions/_jsonutils.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/azure/functions/_jsonutils.py b/azure/functions/_jsonutils.py index 3b077f15..914bcb8f 100644 --- a/azure/functions/_jsonutils.py +++ b/azure/functions/_jsonutils.py @@ -11,10 +11,11 @@ def dumps(self, obj) -> str: def loads(self, s: str): pass + class OrJsonAdapter(JsonInterface): def __init__(self): - import orjson - self.orjson = orjson + import orjson + self.orjson = orjson def dumps(self, obj) -> str: return self.orjson.dumps(obj).decode("utf-8") @@ -55,16 +56,19 @@ def loads(self, s: str): except ImportError: continue + def dumps(obj, **kwargs) -> str: if json_impl is None: raise ImportError("No JSON adapter found") return json_impl.dumps(obj, **kwargs) + def loads(s: str): if json_impl is None: raise ImportError("No JSON adapter found") return json_impl.loads(s) + json = types.SimpleNamespace( dumps=dumps, loads=loads From 58c0dccac2cf5dad4964b85c7a11d254c5be46e1 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 19 May 2025 15:46:51 -0500 Subject: [PATCH 03/13] add simpeljson --- azure/functions/_jsonutils.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/azure/functions/_jsonutils.py b/azure/functions/_jsonutils.py index 914bcb8f..3267a874 100644 --- a/azure/functions/_jsonutils.py +++ b/azure/functions/_jsonutils.py @@ -36,6 +36,18 @@ def loads(self, s: str): return self.ujson.loads(s) +class SimpleJsonAdapter(JsonInterface): + def __init__(self): + import simplejson + self.simplejson = simplejson + + def dumps(self, obj) -> str: + return self.simplejson.dumps(obj) + + def loads(self, s: str): + return self.simplejson.loads(s) + + class StdJsonAdapter(JsonInterface): def __init__(self): import json @@ -49,7 +61,7 @@ def loads(self, s: str): json_impl = None -for adapter_cls in (OrJsonAdapter, UJsonAdapter, StdJsonAdapter): +for adapter_cls in (OrJsonAdapter, UJsonAdapter, SimpleJsonAdapter, StdJsonAdapter): try: json_impl = adapter_cls() break From ede39cf14771b86e5268dd272671d2fe7ab7fd70 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Mon, 19 May 2025 17:04:18 -0500 Subject: [PATCH 04/13] format --- azure/functions/_jsonutils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/azure/functions/_jsonutils.py b/azure/functions/_jsonutils.py index 3267a874..05f3dda4 100644 --- a/azure/functions/_jsonutils.py +++ b/azure/functions/_jsonutils.py @@ -61,7 +61,8 @@ def loads(self, s: str): json_impl = None -for adapter_cls in (OrJsonAdapter, UJsonAdapter, SimpleJsonAdapter, StdJsonAdapter): +for adapter_cls in (OrJsonAdapter, UJsonAdapter, SimpleJsonAdapter, + StdJsonAdapter): try: json_impl = adapter_cls() break From 6d97f9a3bb813354c2ec53944a1da1a607e7049c Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 20 May 2025 15:00:03 -0500 Subject: [PATCH 05/13] orjson only --- azure/functions/_jsonutils.py | 60 +++++++++-------------------------- 1 file changed, 15 insertions(+), 45 deletions(-) diff --git a/azure/functions/_jsonutils.py b/azure/functions/_jsonutils.py index 05f3dda4..e26dde88 100644 --- a/azure/functions/_jsonutils.py +++ b/azure/functions/_jsonutils.py @@ -1,14 +1,15 @@ from abc import ABC, abstractmethod -import types +from typing import Any, Union +from types import SimpleNamespace class JsonInterface(ABC): @abstractmethod - def dumps(self, obj) -> str: + def dumps(self, obj: Any, **kwargs: Any) -> str: pass @abstractmethod - def loads(self, s: str): + def loads(self, s: Union[str, bytes, bytearray]) -> Any: pass @@ -17,72 +18,41 @@ def __init__(self): import orjson self.orjson = orjson - def dumps(self, obj) -> str: + def dumps(self, obj: Any, **kwargs: Any) -> str: + # orjson.dumps returns bytes, decode to str return self.orjson.dumps(obj).decode("utf-8") - def loads(self, s: str): + def loads(self, s: Union[str, bytes, bytearray]) -> Any: return self.orjson.loads(s) -class UJsonAdapter(JsonInterface): - def __init__(self): - import ujson - self.ujson = ujson - - def dumps(self, obj) -> str: - return self.ujson.dumps(obj) - - def loads(self, s: str): - return self.ujson.loads(s) - - -class SimpleJsonAdapter(JsonInterface): - def __init__(self): - import simplejson - self.simplejson = simplejson - - def dumps(self, obj) -> str: - return self.simplejson.dumps(obj) - - def loads(self, s: str): - return self.simplejson.loads(s) - - class StdJsonAdapter(JsonInterface): def __init__(self): import json self.json = json - def dumps(self, obj, **kwargs) -> str: + def dumps(self, obj: Any, **kwargs: Any) -> str: return self.json.dumps(obj, **kwargs) - def loads(self, s: str): + def loads(self, s: Union[str, bytes, bytearray]) -> Any: return self.json.loads(s) -json_impl = None -for adapter_cls in (OrJsonAdapter, UJsonAdapter, SimpleJsonAdapter, - StdJsonAdapter): - try: - json_impl = adapter_cls() - break - except ImportError: - continue +try: + json_impl: JsonInterface = OrJsonAdapter() +except ImportError: + json_impl = StdJsonAdapter() def dumps(obj, **kwargs) -> str: - if json_impl is None: - raise ImportError("No JSON adapter found") return json_impl.dumps(obj, **kwargs) -def loads(s: str): - if json_impl is None: - raise ImportError("No JSON adapter found") +def loads(s: Union[str, bytes, bytearray]) -> Any: return json_impl.loads(s) -json = types.SimpleNamespace( +json = SimpleNamespace( dumps=dumps, loads=loads ) From 309d467255de0813d6cc4b6560b7e28f2e7e99d2 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 20 May 2025 15:44:08 -0500 Subject: [PATCH 06/13] fix --- azure/functions/_jsonutils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/azure/functions/_jsonutils.py b/azure/functions/_jsonutils.py index e26dde88..666627c9 100644 --- a/azure/functions/_jsonutils.py +++ b/azure/functions/_jsonutils.py @@ -1,4 +1,5 @@ from abc import ABC, abstractmethod +import logging from typing import Any, Union from types import SimpleNamespace @@ -40,6 +41,7 @@ def loads(self, s: Union[str, bytes, bytearray]) -> Any: try: json_impl: JsonInterface = OrJsonAdapter() + logging.info("Using orjson as the JSON backend") except ImportError: json_impl = StdJsonAdapter() From 441df7d1516d1f26415955c2affab7f146b111c0 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 20 May 2025 15:46:33 -0500 Subject: [PATCH 07/13] fix --- azure/functions/_jsonutils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/azure/functions/_jsonutils.py b/azure/functions/_jsonutils.py index 666627c9..69174ce8 100644 --- a/azure/functions/_jsonutils.py +++ b/azure/functions/_jsonutils.py @@ -41,7 +41,6 @@ def loads(self, s: Union[str, bytes, bytearray]) -> Any: try: json_impl: JsonInterface = OrJsonAdapter() - logging.info("Using orjson as the JSON backend") except ImportError: json_impl = StdJsonAdapter() From d5d093405df3ff79b5dedc627409c97f636630d0 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 20 May 2025 16:04:18 -0500 Subject: [PATCH 08/13] Fix --- azure/functions/_jsonutils.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/azure/functions/_jsonutils.py b/azure/functions/_jsonutils.py index 69174ce8..b5c85760 100644 --- a/azure/functions/_jsonutils.py +++ b/azure/functions/_jsonutils.py @@ -1,9 +1,15 @@ from abc import ABC, abstractmethod -import logging from typing import Any, Union from types import SimpleNamespace +""" +Azure Functions JSON utilities. +This module provides a JSON interface that can be used to serialize and +deserialize objects to and from JSON format. It supports both the `orjson` +and the standard `json` libraries, falling back to the standard library +if `orjson` is not available (installed). +""" class JsonInterface(ABC): @abstractmethod def dumps(self, obj: Any, **kwargs: Any) -> str: From cd172a635aa68918efb447a39e3e265f1c44e6b1 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Tue, 20 May 2025 16:19:09 -0500 Subject: [PATCH 09/13] pydoc --- azure/functions/_jsonutils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/azure/functions/_jsonutils.py b/azure/functions/_jsonutils.py index b5c85760..92009e81 100644 --- a/azure/functions/_jsonutils.py +++ b/azure/functions/_jsonutils.py @@ -10,6 +10,8 @@ and the standard `json` libraries, falling back to the standard library if `orjson` is not available (installed). """ + + class JsonInterface(ABC): @abstractmethod def dumps(self, obj: Any, **kwargs: Any) -> str: From f02c7e155fe736f55e2619b26f7701000a2145ca Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 22 May 2025 14:31:16 -0500 Subject: [PATCH 10/13] add to files --- azure/functions/_http.py | 2 +- azure/functions/_jsonutils.py | 8 ++++++++ azure/functions/_queue.py | 2 +- azure/functions/_sql.py | 2 +- azure/functions/cosmosdb.py | 2 +- azure/functions/eventgrid.py | 2 +- azure/functions/eventhub.py | 2 +- azure/functions/extension/extension_meta.py | 2 +- azure/functions/http.py | 2 +- azure/functions/kafka.py | 2 +- azure/functions/meta.py | 2 +- azure/functions/mysql.py | 2 +- azure/functions/queue.py | 2 +- azure/functions/servicebus.py | 2 +- azure/functions/sql.py | 2 +- azure/functions/timer.py | 2 +- 16 files changed, 23 insertions(+), 15 deletions(-) diff --git a/azure/functions/_http.py b/azure/functions/_http.py index 7e349b1b..267425c4 100644 --- a/azure/functions/_http.py +++ b/azure/functions/_http.py @@ -4,10 +4,10 @@ import collections.abc import http import io -import json import types import typing +from ._jsonutils import json from werkzeug import formparser as _wk_parser from werkzeug import http as _wk_http from werkzeug.datastructures import (Headers, FileStorage, MultiDict, diff --git a/azure/functions/_jsonutils.py b/azure/functions/_jsonutils.py index 92009e81..e7965812 100644 --- a/azure/functions/_jsonutils.py +++ b/azure/functions/_jsonutils.py @@ -1,3 +1,6 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + from abc import ABC, abstractmethod from typing import Any, Union from types import SimpleNamespace @@ -28,6 +31,11 @@ def __init__(self): self.orjson = orjson def dumps(self, obj: Any, **kwargs: Any) -> str: + if kwargs: + # orjson doesn't support keyword arguments + import json + return json.dumps(obj, **kwargs) + # orjson.dumps returns bytes, decode to str return self.orjson.dumps(obj).decode("utf-8") diff --git a/azure/functions/_queue.py b/azure/functions/_queue.py index c6c7d094..85d574ce 100644 --- a/azure/functions/_queue.py +++ b/azure/functions/_queue.py @@ -2,10 +2,10 @@ # Licensed under the MIT License. import datetime -import json import typing from . import _abc +from ._jsonutils import json class QueueMessage(_abc.QueueMessage): diff --git a/azure/functions/_sql.py b/azure/functions/_sql.py index 3d70a1a9..5b1c71c2 100644 --- a/azure/functions/_sql.py +++ b/azure/functions/_sql.py @@ -2,7 +2,7 @@ # Licensed under the MIT License. import abc import collections -import json +from ._jsonutils import json class BaseSqlRow(abc.ABC): diff --git a/azure/functions/cosmosdb.py b/azure/functions/cosmosdb.py index 1edc78af..e8dc139f 100644 --- a/azure/functions/cosmosdb.py +++ b/azure/functions/cosmosdb.py @@ -2,10 +2,10 @@ # Licensed under the MIT License. import collections.abc -import json import typing from azure.functions import _cosmosdb as cdb +from ._jsonutils import json from . import meta diff --git a/azure/functions/eventgrid.py b/azure/functions/eventgrid.py index e76f5dde..3cddd9e1 100644 --- a/azure/functions/eventgrid.py +++ b/azure/functions/eventgrid.py @@ -3,10 +3,10 @@ import collections import datetime -import json from typing import Optional, List, Any, Dict, Union from azure.functions import _eventgrid as azf_eventgrid +from ._jsonutils import json from . import meta from .meta import Datum diff --git a/azure/functions/eventhub.py b/azure/functions/eventhub.py index 6aab2be5..8888aaed 100644 --- a/azure/functions/eventhub.py +++ b/azure/functions/eventhub.py @@ -1,10 +1,10 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -import json from typing import Dict, Any, List, Union, Optional, Mapping from azure.functions import _eventhub +from ._jsonutils import json from . import meta diff --git a/azure/functions/extension/extension_meta.py b/azure/functions/extension/extension_meta.py index 2536d6fb..fde3622f 100644 --- a/azure/functions/extension/extension_meta.py +++ b/azure/functions/extension/extension_meta.py @@ -3,12 +3,12 @@ from typing import Optional, Union, Dict, List import abc -import json from .app_extension_hooks import AppExtensionHooks from .func_extension_hooks import FuncExtensionHooks from .extension_hook_meta import ExtensionHookMeta from .extension_scope import ExtensionScope from .function_extension_exception import FunctionExtensionException +from .._jsonutils import json class ExtensionMeta(abc.ABCMeta): diff --git a/azure/functions/http.py b/azure/functions/http.py index 734f43eb..a1da5a7f 100644 --- a/azure/functions/http.py +++ b/azure/functions/http.py @@ -1,7 +1,6 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -import json import logging import sys import typing @@ -9,6 +8,7 @@ from azure.functions import _abc as azf_abc from azure.functions import _http as azf_http +from ._jsonutils import json from . import meta from werkzeug.datastructures import Headers diff --git a/azure/functions/kafka.py b/azure/functions/kafka.py index 4693e9d1..1e792108 100644 --- a/azure/functions/kafka.py +++ b/azure/functions/kafka.py @@ -2,13 +2,13 @@ # Licensed under the MIT License. import typing -import json from typing import Any, List from . import meta from ._kafka import AbstractKafkaEvent +from ._jsonutils import json class KafkaEvent(AbstractKafkaEvent): diff --git a/azure/functions/meta.py b/azure/functions/meta.py index 2ca92563..09314f8d 100644 --- a/azure/functions/meta.py +++ b/azure/functions/meta.py @@ -4,10 +4,10 @@ import abc import collections.abc import datetime -import json import re from typing import Dict, Optional, Union, Tuple, Mapping, Any +from ._jsonutils import json from ._thirdparty import typing_inspect from ._utils import ( try_parse_datetime_with_formats, diff --git a/azure/functions/mysql.py b/azure/functions/mysql.py index 06a04a56..cbaf18e7 100644 --- a/azure/functions/mysql.py +++ b/azure/functions/mysql.py @@ -2,12 +2,12 @@ # Licensed under the MIT License. import collections.abc -import json import typing from azure.functions import _mysql as mysql from . import meta +from ._jsonutils import json class MySqlConverter(meta.InConverter, meta.OutConverter, diff --git a/azure/functions/queue.py b/azure/functions/queue.py index d39c56e5..77b8354d 100644 --- a/azure/functions/queue.py +++ b/azure/functions/queue.py @@ -3,13 +3,13 @@ import collections.abc import datetime -import json from typing import List, Dict, Any, Union, Optional from azure.functions import _abc as azf_abc from azure.functions import _queue as azf_queue from . import meta +from ._jsonutils import json class QueueMessage(azf_queue.QueueMessage): diff --git a/azure/functions/servicebus.py b/azure/functions/servicebus.py index 72a9d254..bc04bfde 100644 --- a/azure/functions/servicebus.py +++ b/azure/functions/servicebus.py @@ -2,12 +2,12 @@ # Licensed under the MIT License. import datetime -import json from typing import Dict, Any, List, Union, Optional, Mapping, cast from azure.functions import _servicebus as azf_sbus from . import meta +from ._jsonutils import json class ServiceBusMessage(azf_sbus.ServiceBusMessage): diff --git a/azure/functions/sql.py b/azure/functions/sql.py index f8288303..d385ee6e 100644 --- a/azure/functions/sql.py +++ b/azure/functions/sql.py @@ -2,12 +2,12 @@ # Licensed under the MIT License. import collections.abc -import json import typing from azure.functions import _sql as sql from . import meta +from ._jsonutils import json class SqlConverter(meta.InConverter, meta.OutConverter, diff --git a/azure/functions/timer.py b/azure/functions/timer.py index 92ef71c3..87d0fd36 100644 --- a/azure/functions/timer.py +++ b/azure/functions/timer.py @@ -1,11 +1,11 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -import json import typing from azure.functions import _abc as azf_abc from . import meta +from ._jsonutils import json class TimerRequest(azf_abc.TimerRequest): From e849e80e3cf587732739223a643f9a9d8b7b1c47 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 22 May 2025 14:45:28 -0500 Subject: [PATCH 11/13] rm kwargs --- azure/functions/_jsonutils.py | 17 ++++++----------- azure/functions/_mysql.py | 3 ++- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/azure/functions/_jsonutils.py b/azure/functions/_jsonutils.py index e7965812..6d7527bc 100644 --- a/azure/functions/_jsonutils.py +++ b/azure/functions/_jsonutils.py @@ -17,7 +17,7 @@ class JsonInterface(ABC): @abstractmethod - def dumps(self, obj: Any, **kwargs: Any) -> str: + def dumps(self, obj: Any) -> str: pass @abstractmethod @@ -30,12 +30,7 @@ def __init__(self): import orjson self.orjson = orjson - def dumps(self, obj: Any, **kwargs: Any) -> str: - if kwargs: - # orjson doesn't support keyword arguments - import json - return json.dumps(obj, **kwargs) - + def dumps(self, obj: Any) -> str: # orjson.dumps returns bytes, decode to str return self.orjson.dumps(obj).decode("utf-8") @@ -48,8 +43,8 @@ def __init__(self): import json self.json = json - def dumps(self, obj: Any, **kwargs: Any) -> str: - return self.json.dumps(obj, **kwargs) + def dumps(self, obj: Any) -> str: + return self.json.dumps(obj) def loads(self, s: Union[str, bytes, bytearray]) -> Any: return self.json.loads(s) @@ -61,8 +56,8 @@ def loads(self, s: Union[str, bytes, bytearray]) -> Any: json_impl = StdJsonAdapter() -def dumps(obj, **kwargs) -> str: - return json_impl.dumps(obj, **kwargs) +def dumps(obj: Any) -> str: + return json_impl.dumps(obj) def loads(s: Union[str, bytes, bytearray]) -> Any: diff --git a/azure/functions/_mysql.py b/azure/functions/_mysql.py index 9c7515d9..1f6b4072 100644 --- a/azure/functions/_mysql.py +++ b/azure/functions/_mysql.py @@ -2,7 +2,8 @@ # Licensed under the MIT License. import abc import collections -import json + +from ._jsonutils import json class BaseMySqlRow(abc.ABC): From 4046e2e7013beee20bbac8e9ae90aa48c6268bf4 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 22 May 2025 16:15:30 -0500 Subject: [PATCH 12/13] order --- azure/functions/_sql.py | 1 + azure/functions/http.py | 2 +- azure/functions/kafka.py | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/azure/functions/_sql.py b/azure/functions/_sql.py index 5b1c71c2..166b3af4 100644 --- a/azure/functions/_sql.py +++ b/azure/functions/_sql.py @@ -2,6 +2,7 @@ # Licensed under the MIT License. import abc import collections + from ._jsonutils import json diff --git a/azure/functions/http.py b/azure/functions/http.py index a1da5a7f..5a9e10c3 100644 --- a/azure/functions/http.py +++ b/azure/functions/http.py @@ -8,8 +8,8 @@ from azure.functions import _abc as azf_abc from azure.functions import _http as azf_http -from ._jsonutils import json from . import meta +from ._jsonutils import json from werkzeug.datastructures import Headers diff --git a/azure/functions/kafka.py b/azure/functions/kafka.py index 1e792108..f71bb2c4 100644 --- a/azure/functions/kafka.py +++ b/azure/functions/kafka.py @@ -6,9 +6,9 @@ from typing import Any, List from . import meta +from ._jsonutils import json from ._kafka import AbstractKafkaEvent -from ._jsonutils import json class KafkaEvent(AbstractKafkaEvent): From 0404267c616329bcb93b0f3f0a65599fd6ecea78 Mon Sep 17 00:00:00 2001 From: Evan Roman Date: Thu, 29 May 2025 01:22:22 -0500 Subject: [PATCH 13/13] fb --- azure/functions/_jsonutils.py | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/azure/functions/_jsonutils.py b/azure/functions/_jsonutils.py index 6d7527bc..2ee0e256 100644 --- a/azure/functions/_jsonutils.py +++ b/azure/functions/_jsonutils.py @@ -15,6 +15,15 @@ """ +try: + import orjson as _orjson +except ImportError: + _orjson = None + +# Standard library is always present +import json as _std_json + + class JsonInterface(ABC): @abstractmethod def dumps(self, obj: Any) -> str: @@ -27,8 +36,8 @@ def loads(self, s: Union[str, bytes, bytearray]) -> Any: class OrJsonAdapter(JsonInterface): def __init__(self): - import orjson - self.orjson = orjson + assert _orjson is not None + self.orjson = _orjson def dumps(self, obj: Any) -> str: # orjson.dumps returns bytes, decode to str @@ -40,8 +49,7 @@ def loads(self, s: Union[str, bytes, bytearray]) -> Any: class StdJsonAdapter(JsonInterface): def __init__(self): - import json - self.json = json + self.json = _std_json def dumps(self, obj: Any) -> str: return self.json.dumps(obj) @@ -50,9 +58,9 @@ def loads(self, s: Union[str, bytes, bytearray]) -> Any: return self.json.loads(s) -try: - json_impl: JsonInterface = OrJsonAdapter() -except ImportError: +if _orjson is not None: + json_impl = OrJsonAdapter() +else: json_impl = StdJsonAdapter()