We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Encoding bytestrings using NumpyJSONEncoder triggers RecursionError 
The following code

```python
import json
from qcodes.utils.helpers import NumpyJSONEncoder

a = {        "voltageDC": {
            "__class__": "qcodes_fluke8842aDriver_2.voltageDC",
            "full_name": "fDMMInst1_voltageDC",
            "value": 5.7e-05,
            "ts": "2022-09-12 10:18:34",
            "raw_value": b"+000.057E-3\r\n",
            "name": "voltageDC",
            "unit": "V",
            "inter_delay": 0,
            "post_delay": 0,
            "instrument": "qcodes_fluke8842aDriver_2.Fluke8842aDriver",
            "instrument_name": "fDMMInst1",
            "label": "voltageDC",
        }}
json.dumps(a,  cls=NumpyJSONEncoder)
```

trigger

```
---------------------------------------------------------------------------
RecursionError                            Traceback (most recent call last)
Cell In [19], line 18
      2 from qcodes.utils.helpers import NumpyJSONEncoder
      4 a = {        "voltageDC": {
      5             "__class__": "qcodes_fluke8842aDriver_2.voltageDC",
      6             "full_name": "fDMMInst1_voltageDC",
   (...)
     16             "label": "voltageDC",
     17         }}
---> 18 json.dumps(a,  cls=NumpyJSONEncoder)

File ~\Miniconda3\envs\qcodespip38\lib\json\__init__.py:234, in dumps(obj, skipkeys, ensure_ascii, check_circular, allow_nan, cls, indent, separators, default, sort_keys, **kw)
    232 if cls is None:
    233     cls = JSONEncoder
--> 234 return cls(
    235     skipkeys=skipkeys, ensure_ascii=ensure_ascii,
    236     check_circular=check_circular, allow_nan=allow_nan, indent=indent,
    237     separators=separators, default=default, sort_keys=sort_keys,
    238     **kw).encode(obj)

File ~\Miniconda3\envs\qcodespip38\lib\json\encoder.py:199, in JSONEncoder.encode(self, o)
    195         return encode_basestring(o)
    196 # This doesn't pass the iterator directly to ''.join() because the
    197 # exceptions aren't as detailed.  The list call should be roughly
    198 # equivalent to the PySequence_Fast that ''.join() would do.
--> 199 chunks = self.iterencode(o, _one_shot=True)
    200 if not isinstance(chunks, (list, tuple)):
    201     chunks = list(chunks)

File ~\Miniconda3\envs\qcodespip38\lib\json\encoder.py:257, in JSONEncoder.iterencode(self, o, _one_shot)
    252 else:
    253     _iterencode = _make_iterencode(
    254         markers, self.default, _encoder, self.indent, floatstr,
    255         self.key_separator, self.item_separator, self.sort_keys,
    256         self.skipkeys, _one_shot)
--> 257 return _iterencode(o, 0)

File ~\source\repos\Qcodes\qcodes\utils\json_utils.py:54, in NumpyJSONEncoder.default(self, obj)
     51 elif isinstance(obj, np.ndarray):
     52     # for numpy arrays
     53     return obj.tolist()
---> 54 elif isinstance(obj, numbers.Complex) and not isinstance(obj, numbers.Real):
     55     return {
     56         "__dtype__": "complex",
     57         "re": float(obj.real),
     58         "im": float(obj.imag),
     59     }
     60 elif isinstance(obj, uncertainties.UFloat):

File ~\Miniconda3\envs\qcodespip38\lib\abc.py:98, in ABCMeta.__instancecheck__(cls, instance)
     96 def __instancecheck__(cls, instance):
     97     """Override for isinstance(instance, cls)."""
---> 98     return _abc_instancecheck(cls, instance)

RecursionError: maximum recursion depth exceeded in comparison
```

This should either fail with a more meaningful error, skip the problematic element or correctly handle the bytestring. 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `qcodes/utils/json_utils.py`
Content:
```
1 import collections
2 import json
3 import numbers
4 import warnings
5 from typing import Any
6 
7 import numpy as np
8 
9 
10 class NumpyJSONEncoder(json.JSONEncoder):
11     """
12     This JSON encoder adds support for serializing types that the built-in
13     ``json`` module does not support out-of-the-box. See the docstring of the
14     ``default`` method for the description of all conversions.
15     """
16 
17     def default(self, obj: Any) -> Any:
18         """
19         List of conversions that this encoder performs:
20 
21         * ``numpy.generic`` (all integer, floating, and other types) gets
22           converted to its python equivalent using its ``item`` method (see
23           ``numpy`` docs for more information,
24           https://docs.scipy.org/doc/numpy/reference/arrays.scalars.html).
25         * ``numpy.ndarray`` gets converted to python list using its ``tolist``
26           method.
27         * Complex number (a number that conforms to ``numbers.Complex`` ABC) gets
28           converted to a dictionary with fields ``re`` and ``im`` containing floating
29           numbers for the real and imaginary parts respectively, and a field
30           ``__dtype__`` containing value ``complex``.
31         * Numbers with uncertainties  (numbers that conforms to ``uncertainties.UFloat``) get
32           converted to a dictionary with fields ``nominal_value`` and ``std_dev`` containing floating
33           numbers for the nominal and uncertainty parts respectively, and a field
34           ``__dtype__`` containing value ``UFloat``.
35         * Object with a ``_JSONEncoder`` method get converted the return value of
36           that method.
37         * Objects which support the pickle protocol get converted using the
38           data provided by that protocol.
39         * Other objects which cannot be serialized get converted to their
40           string representation (using the ``str`` function).
41         """
42         import uncertainties
43 
44         if isinstance(obj, np.generic) and not isinstance(obj, np.complexfloating):
45             # for numpy scalars
46             return obj.item()
47         elif isinstance(obj, np.ndarray):
48             # for numpy arrays
49             return obj.tolist()
50         elif isinstance(obj, numbers.Complex) and not isinstance(obj, numbers.Real):
51             return {
52                 "__dtype__": "complex",
53                 "re": float(obj.real),
54                 "im": float(obj.imag),
55             }
56         elif isinstance(obj, uncertainties.UFloat):
57             return {
58                 "__dtype__": "UFloat",
59                 "nominal_value": float(obj.nominal_value),
60                 "std_dev": float(obj.std_dev),
61             }
62         elif hasattr(obj, "_JSONEncoder"):
63             # Use object's custom JSON encoder
64             jsosencode = getattr(obj, "_JSONEncoder")
65             return jsosencode()
66         else:
67             try:
68                 s = super().default(obj)
69             except TypeError:
70                 # json does not support dumping UserDict but
71                 # we can dump the dict stored internally in the
72                 # UserDict
73                 if isinstance(obj, collections.UserDict):
74                     return obj.data
75                 # See if the object supports the pickle protocol.
76                 # If so, we should be able to use that to serialize.
77                 if hasattr(obj, "__getnewargs__"):
78                     return {
79                         "__class__": type(obj).__name__,
80                         "__args__": getattr(obj, "__getnewargs__")(),
81                     }
82                 else:
83                     # we cannot convert the object to JSON, just take a string
84                     s = str(obj)
85             return s
86
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/qcodes/utils/json_utils.py b/qcodes/utils/json_utils.py
--- a/qcodes/utils/json_utils.py
+++ b/qcodes/utils/json_utils.py
@@ -74,7 +74,12 @@
                     return obj.data
                 # See if the object supports the pickle protocol.
                 # If so, we should be able to use that to serialize.
-                if hasattr(obj, "__getnewargs__"):
+                # __getnewargs__ will return bytes for a bytes object
+                # causing an infinte recursion, so we do not
+                # try to pickle bytes or bytearrays
+                if hasattr(obj, "__getnewargs__") and not isinstance(
+                    obj, (bytes, bytearray)
+                ):
                     return {
                         "__class__": type(obj).__name__,
                         "__args__": getattr(obj, "__getnewargs__")(),

{"golden_diff": "diff --git a/qcodes/utils/json_utils.py b/qcodes/utils/json_utils.py\n--- a/qcodes/utils/json_utils.py\n+++ b/qcodes/utils/json_utils.py\n@@ -74,7 +74,12 @@\n                     return obj.data\n                 # See if the object supports the pickle protocol.\n                 # If so, we should be able to use that to serialize.\n-                if hasattr(obj, \"__getnewargs__\"):\n+                # __getnewargs__ will return bytes for a bytes object\n+                # causing an infinte recursion, so we do not\n+                # try to pickle bytes or bytearrays\n+                if hasattr(obj, \"__getnewargs__\") and not isinstance(\n+                    obj, (bytes, bytearray)\n+                ):\n                     return {\n                         \"__class__\": type(obj).__name__,\n                         \"__args__\": getattr(obj, \"__getnewargs__\")(),\n", "issue": "Encoding bytestrings using NumpyJSONEncoder triggers RecursionError \nThe following code\r\n\r\n```python\r\nimport json\r\nfrom qcodes.utils.helpers import NumpyJSONEncoder\r\n\r\na = {        \"voltageDC\": {\r\n            \"__class__\": \"qcodes_fluke8842aDriver_2.voltageDC\",\r\n            \"full_name\": \"fDMMInst1_voltageDC\",\r\n            \"value\": 5.7e-05,\r\n            \"ts\": \"2022-09-12 10:18:34\",\r\n            \"raw_value\": b\"+000.057E-3\\r\\n\",\r\n            \"name\": \"voltageDC\",\r\n            \"unit\": \"V\",\r\n            \"inter_delay\": 0,\r\n            \"post_delay\": 0,\r\n            \"instrument\": \"qcodes_fluke8842aDriver_2.Fluke8842aDriver\",\r\n            \"instrument_name\": \"fDMMInst1\",\r\n            \"label\": \"voltageDC\",\r\n        }}\r\njson.dumps(a,  cls=NumpyJSONEncoder)\r\n```\r\n\r\ntrigger\r\n\r\n```\r\n---------------------------------------------------------------------------\r\nRecursionError                            Traceback (most recent call last)\r\nCell In [19], line 18\r\n      2 from qcodes.utils.helpers import NumpyJSONEncoder\r\n      4 a = {        \"voltageDC\": {\r\n      5             \"__class__\": \"qcodes_fluke8842aDriver_2.voltageDC\",\r\n      6             \"full_name\": \"fDMMInst1_voltageDC\",\r\n   (...)\r\n     16             \"label\": \"voltageDC\",\r\n     17         }}\r\n---> 18 json.dumps(a,  cls=NumpyJSONEncoder)\r\n\r\nFile ~\\Miniconda3\\envs\\qcodespip38\\lib\\json\\__init__.py:234, in dumps(obj, skipkeys, ensure_ascii, check_circular, allow_nan, cls, indent, separators, default, sort_keys, **kw)\r\n    232 if cls is None:\r\n    233     cls = JSONEncoder\r\n--> 234 return cls(\r\n    235     skipkeys=skipkeys, ensure_ascii=ensure_ascii,\r\n    236     check_circular=check_circular, allow_nan=allow_nan, indent=indent,\r\n    237     separators=separators, default=default, sort_keys=sort_keys,\r\n    238     **kw).encode(obj)\r\n\r\nFile ~\\Miniconda3\\envs\\qcodespip38\\lib\\json\\encoder.py:199, in JSONEncoder.encode(self, o)\r\n    195         return encode_basestring(o)\r\n    196 # This doesn't pass the iterator directly to ''.join() because the\r\n    197 # exceptions aren't as detailed.  The list call should be roughly\r\n    198 # equivalent to the PySequence_Fast that ''.join() would do.\r\n--> 199 chunks = self.iterencode(o, _one_shot=True)\r\n    200 if not isinstance(chunks, (list, tuple)):\r\n    201     chunks = list(chunks)\r\n\r\nFile ~\\Miniconda3\\envs\\qcodespip38\\lib\\json\\encoder.py:257, in JSONEncoder.iterencode(self, o, _one_shot)\r\n    252 else:\r\n    253     _iterencode = _make_iterencode(\r\n    254         markers, self.default, _encoder, self.indent, floatstr,\r\n    255         self.key_separator, self.item_separator, self.sort_keys,\r\n    256         self.skipkeys, _one_shot)\r\n--> 257 return _iterencode(o, 0)\r\n\r\nFile ~\\source\\repos\\Qcodes\\qcodes\\utils\\json_utils.py:54, in NumpyJSONEncoder.default(self, obj)\r\n     51 elif isinstance(obj, np.ndarray):\r\n     52     # for numpy arrays\r\n     53     return obj.tolist()\r\n---> 54 elif isinstance(obj, numbers.Complex) and not isinstance(obj, numbers.Real):\r\n     55     return {\r\n     56         \"__dtype__\": \"complex\",\r\n     57         \"re\": float(obj.real),\r\n     58         \"im\": float(obj.imag),\r\n     59     }\r\n     60 elif isinstance(obj, uncertainties.UFloat):\r\n\r\nFile ~\\Miniconda3\\envs\\qcodespip38\\lib\\abc.py:98, in ABCMeta.__instancecheck__(cls, instance)\r\n     96 def __instancecheck__(cls, instance):\r\n     97     \"\"\"Override for isinstance(instance, cls).\"\"\"\r\n---> 98     return _abc_instancecheck(cls, instance)\r\n\r\nRecursionError: maximum recursion depth exceeded in comparison\r\n```\r\n\r\nThis should either fail with a more meaningful error, skip the problematic element or correctly handle the bytestring. \n", "before_files": [{"content": "import collections\nimport json\nimport numbers\nimport warnings\nfrom typing import Any\n\nimport numpy as np\n\n\nclass NumpyJSONEncoder(json.JSONEncoder):\n    \"\"\"\n    This JSON encoder adds support for serializing types that the built-in\n    ``json`` module does not support out-of-the-box. See the docstring of the\n    ``default`` method for the description of all conversions.\n    \"\"\"\n\n    def default(self, obj: Any) -> Any:\n        \"\"\"\n        List of conversions that this encoder performs:\n\n        * ``numpy.generic`` (all integer, floating, and other types) gets\n          converted to its python equivalent using its ``item`` method (see\n          ``numpy`` docs for more information,\n          https://docs.scipy.org/doc/numpy/reference/arrays.scalars.html).\n        * ``numpy.ndarray`` gets converted to python list using its ``tolist``\n          method.\n        * Complex number (a number that conforms to ``numbers.Complex`` ABC) gets\n          converted to a dictionary with fields ``re`` and ``im`` containing floating\n          numbers for the real and imaginary parts respectively, and a field\n          ``__dtype__`` containing value ``complex``.\n        * Numbers with uncertainties  (numbers that conforms to ``uncertainties.UFloat``) get\n          converted to a dictionary with fields ``nominal_value`` and ``std_dev`` containing floating\n          numbers for the nominal and uncertainty parts respectively, and a field\n          ``__dtype__`` containing value ``UFloat``.\n        * Object with a ``_JSONEncoder`` method get converted the return value of\n          that method.\n        * Objects which support the pickle protocol get converted using the\n          data provided by that protocol.\n        * Other objects which cannot be serialized get converted to their\n          string representation (using the ``str`` function).\n        \"\"\"\n        import uncertainties\n\n        if isinstance(obj, np.generic) and not isinstance(obj, np.complexfloating):\n            # for numpy scalars\n            return obj.item()\n        elif isinstance(obj, np.ndarray):\n            # for numpy arrays\n            return obj.tolist()\n        elif isinstance(obj, numbers.Complex) and not isinstance(obj, numbers.Real):\n            return {\n                \"__dtype__\": \"complex\",\n                \"re\": float(obj.real),\n                \"im\": float(obj.imag),\n            }\n        elif isinstance(obj, uncertainties.UFloat):\n            return {\n                \"__dtype__\": \"UFloat\",\n                \"nominal_value\": float(obj.nominal_value),\n                \"std_dev\": float(obj.std_dev),\n            }\n        elif hasattr(obj, \"_JSONEncoder\"):\n            # Use object's custom JSON encoder\n            jsosencode = getattr(obj, \"_JSONEncoder\")\n            return jsosencode()\n        else:\n            try:\n                s = super().default(obj)\n            except TypeError:\n                # json does not support dumping UserDict but\n                # we can dump the dict stored internally in the\n                # UserDict\n                if isinstance(obj, collections.UserDict):\n                    return obj.data\n                # See if the object supports the pickle protocol.\n                # If so, we should be able to use that to serialize.\n                if hasattr(obj, \"__getnewargs__\"):\n                    return {\n                        \"__class__\": type(obj).__name__,\n                        \"__args__\": getattr(obj, \"__getnewargs__\")(),\n                    }\n                else:\n                    # we cannot convert the object to JSON, just take a string\n                    s = str(obj)\n            return s\n", "path": "qcodes/utils/json_utils.py"}], "after_files": [{"content": "import collections\nimport json\nimport numbers\nimport warnings\nfrom typing import Any\n\nimport numpy as np\n\n\nclass NumpyJSONEncoder(json.JSONEncoder):\n    \"\"\"\n    This JSON encoder adds support for serializing types that the built-in\n    ``json`` module does not support out-of-the-box. See the docstring of the\n    ``default`` method for the description of all conversions.\n    \"\"\"\n\n    def default(self, obj: Any) -> Any:\n        \"\"\"\n        List of conversions that this encoder performs:\n\n        * ``numpy.generic`` (all integer, floating, and other types) gets\n          converted to its python equivalent using its ``item`` method (see\n          ``numpy`` docs for more information,\n          https://docs.scipy.org/doc/numpy/reference/arrays.scalars.html).\n        * ``numpy.ndarray`` gets converted to python list using its ``tolist``\n          method.\n        * Complex number (a number that conforms to ``numbers.Complex`` ABC) gets\n          converted to a dictionary with fields ``re`` and ``im`` containing floating\n          numbers for the real and imaginary parts respectively, and a field\n          ``__dtype__`` containing value ``complex``.\n        * Numbers with uncertainties  (numbers that conforms to ``uncertainties.UFloat``) get\n          converted to a dictionary with fields ``nominal_value`` and ``std_dev`` containing floating\n          numbers for the nominal and uncertainty parts respectively, and a field\n          ``__dtype__`` containing value ``UFloat``.\n        * Object with a ``_JSONEncoder`` method get converted the return value of\n          that method.\n        * Objects which support the pickle protocol get converted using the\n          data provided by that protocol.\n        * Other objects which cannot be serialized get converted to their\n          string representation (using the ``str`` function).\n        \"\"\"\n        import uncertainties\n\n        if isinstance(obj, np.generic) and not isinstance(obj, np.complexfloating):\n            # for numpy scalars\n            return obj.item()\n        elif isinstance(obj, np.ndarray):\n            # for numpy arrays\n            return obj.tolist()\n        elif isinstance(obj, numbers.Complex) and not isinstance(obj, numbers.Real):\n            return {\n                \"__dtype__\": \"complex\",\n                \"re\": float(obj.real),\n                \"im\": float(obj.imag),\n            }\n        elif isinstance(obj, uncertainties.UFloat):\n            return {\n                \"__dtype__\": \"UFloat\",\n                \"nominal_value\": float(obj.nominal_value),\n                \"std_dev\": float(obj.std_dev),\n            }\n        elif hasattr(obj, \"_JSONEncoder\"):\n            # Use object's custom JSON encoder\n            jsosencode = getattr(obj, \"_JSONEncoder\")\n            return jsosencode()\n        else:\n            try:\n                s = super().default(obj)\n            except TypeError:\n                # json does not support dumping UserDict but\n                # we can dump the dict stored internally in the\n                # UserDict\n                if isinstance(obj, collections.UserDict):\n                    return obj.data\n                # See if the object supports the pickle protocol.\n                # If so, we should be able to use that to serialize.\n                # __getnewargs__ will return bytes for a bytes object\n                # causing an infinte recursion, so we do not\n                # try to pickle bytes or bytearrays\n                if hasattr(obj, \"__getnewargs__\") and not isinstance(\n                    obj, (bytes, bytearray)\n                ):\n                    return {\n                        \"__class__\": type(obj).__name__,\n                        \"__args__\": getattr(obj, \"__getnewargs__\")(),\n                    }\n                else:\n                    # we cannot convert the object to JSON, just take a string\n                    s = str(obj)\n            return s\n", "path": "qcodes/utils/json_utils.py"}]}