We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[BUG] Can't write objects to JSON
v3.0.14

```python
import pickle
t = ds.create_tensor(f"t/group/f", htype="json", chunk_compression="lz4")
t.append(pickle.dumps("test"))  # pass any pickled object into append gets error
```

```
ValueError: Circular reference detected
```

passing strings and such into this tensor works fine, but for some reason any pickled object or python object that gets pickled gives the above ValueError.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `deeplake/util/json.py`
Content:
```
1 from typing import Any, Dict, List, Optional, Tuple, Union
2 import numpy as np
3 from numpy import ndarray
4 import json
5 import base64
6 from deeplake.core.sample import Sample  # type: ignore
7 
8 Schema = Any
9 
10 
11 scalars = ["int", "float", "bool", "str", "list", "dict", "ndarray", "Sample"]
12 types = ["Any", "Dict", "List", "Optional", "Union"]
13 
14 
15 def _norm_type(typ: str):
16     typ = typ.replace("typing.", "")
17     replacements = {
18         "numpy.ndarray": "ndarray",
19         "np.ndarray": "ndarray",
20         "deeplake.core.sample.Sample": "Sample",
21         "deeplake.Sample": "Sample",
22     }
23     return replacements.get(typ, typ)
24 
25 
26 def _parse_schema(schema: Union[str, Schema]) -> Tuple[str, List[str]]:
27     if getattr(schema, "__module__", None) == "typing":
28         schema = str(schema)
29         validate = False
30     else:
31         validate = True
32 
33     if schema in scalars:
34         return schema, []
35 
36     if "[" not in schema:
37         return _norm_type(schema), []
38 
39     typ, param_string = schema.split("[", 1)
40     typ = _norm_type(typ)
41     assert param_string[-1] == "]"
42     params = []
43     buff = ""
44     level = 0
45     for c in param_string:
46         if c == "[":
47             level += 1
48             buff += c
49         elif c == "]":
50             if level == 0:
51                 if buff:
52                     params.append(buff)
53                 if validate:
54                     _validate_schema(typ, params)
55                 return typ, params
56             else:
57                 buff += c
58                 level -= 1
59         elif c == ",":
60             if level == 0:
61                 params.append(buff)
62                 buff = ""
63             else:
64                 buff += c
65         elif c == " ":
66             continue
67         else:
68             buff += c
69     raise InvalidJsonSchemaException()
70 
71 
72 class InvalidJsonSchemaException(Exception):
73     pass
74 
75 
76 class ArgumentMismatchException(InvalidJsonSchemaException):
77     def __init__(self, typ: str, actual: int, expected: int, exact: bool = False):
78         assert actual != expected
79         gt = actual > expected
80         super(ArgumentMismatchException, self).__init__(
81             f"Too {'many' if gt else 'few'} parameters for {typ};"
82             + f" actual {actual},expected {'exatcly' if exact else ('at most' if gt else 'at least')} {expected}."
83         )
84 
85 
86 def _validate_schema(typ: str, params: List[str]) -> Tuple[str, List[str]]:
87     if typ in scalars:
88         return typ, params
89 
90     if typ not in types:
91         raise InvalidJsonSchemaException(f"Unsupported type: {typ}")
92 
93     def _err(expected_num_params: int, exact: bool = False):
94         raise ArgumentMismatchException(typ, len(params), expected_num_params, exact)
95 
96     if typ == "Any":
97         if params:
98             _err(0)
99     elif typ == "Optional":
100         if len(params) > 1:
101             _err(1)
102     elif typ == "Union":
103         if len(params) == 0:
104             _err(1)
105     elif typ == "List":
106         if len(params) > 1:
107             _err(1)
108     elif typ == "Dict":
109         if len(params) not in (0, 2):
110             _err(2, True)
111     return typ, params
112 
113 
114 def _validate_any(obj: Any, params: List[str]):
115     assert not params
116     return True
117 
118 
119 def _validate_union(obj: Any, params: List[str]):
120     for schema in params:
121         if _validate_object(obj, schema):
122             return True
123     return False
124 
125 
126 def _validate_optional(obj: Any, params: List[str]) -> bool:
127     assert len(params) <= 1
128     if obj is None:
129         return True
130     if params:
131         return _validate_object(obj, params[0])
132     return True
133 
134 
135 def _validate_list(obj: Any, params: List[str]) -> bool:
136     assert len(params) <= 1
137     if not isinstance(obj, (list, tuple)):
138         return False
139     if params:
140         for item in obj:
141             if not _validate_object(item, params[0]):
142                 return False
143     return True
144 
145 
146 def _validate_dict(obj: Any, params: List[str]) -> bool:
147     assert len(params) in (0, 2)
148     if not isinstance(obj, dict):
149         return False
150     if params:
151         assert params[0] in (
152             "str",
153             "Any",
154         ), "Only string keys are allowed for json dicts."
155         for v in obj.values():
156             if not _validate_object(v, params[1]):
157                 return False
158     return True
159 
160 
161 def _validate_nonetype(obj: Any, params: List[str]) -> bool:
162     assert not params
163     return obj is None
164 
165 
166 def _validate_object(obj: Any, schema: Union[str, Schema]) -> bool:
167     typ, params = _parse_schema(schema)
168     if typ in scalars:
169         return isinstance(obj, eval(typ))
170     return globals()[f"_validate_{typ.lower()}"](obj, params)
171 
172 
173 class JsonValidationError(Exception):
174     pass
175 
176 
177 def validate_json_object(obj: Any, schema: Union[str, Schema]) -> None:
178     if obj and not _validate_object(obj, schema):
179         raise JsonValidationError()
180 
181 
182 def validate_json_schema(schema: str):
183     _parse_schema(schema)
184 
185 
186 class HubJsonEncoder(json.JSONEncoder):
187     def default(self, obj):
188         if isinstance(obj, ndarray):
189             return {
190                 "_hub_custom_type": "ndarray",
191                 "data": base64.b64encode(obj.tobytes()).decode(),
192                 "shape": obj.shape,
193                 "dtype": obj.dtype.name,
194             }
195         elif isinstance(obj, Sample):
196             if obj.compression:
197                 return {
198                     "_hub_custom_type": "Sample",
199                     "data": base64.b64encode(obj.buffer).decode(),
200                     "compression": obj.compression,
201                 }
202             else:
203                 return self.default(obj.array)
204         return obj
205 
206 
207 class HubJsonDecoder(json.JSONDecoder):
208     def __init__(self, *args, **kwargs):
209         json.JSONDecoder.__init__(self, object_hook=self.object_hook, *args, **kwargs)
210 
211     def object_hook(self, obj):
212         hub_custom_type = obj.get("_hub_custom_type")
213         if hub_custom_type == "ndarray":
214             return np.frombuffer(
215                 base64.b64decode(obj["data"]), dtype=obj["dtype"]
216             ).reshape(obj["shape"])
217         elif hub_custom_type == "Sample":
218             return Sample(
219                 buffer=base64.b64decode(obj["data"]), compression=obj["compression"]
220             )
221         return obj
222
```
--- 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/deeplake/util/json.py b/deeplake/util/json.py
--- a/deeplake/util/json.py
+++ b/deeplake/util/json.py
@@ -201,6 +201,12 @@
                 }
             else:
                 return self.default(obj.array)
+        elif isinstance(obj, bytes):
+            return {
+                "_hub_custom_type": "bytes",
+                "data": base64.b64encode(obj).decode(),
+            }
+
         return obj
 
 
@@ -218,4 +224,6 @@
             return Sample(
                 buffer=base64.b64decode(obj["data"]), compression=obj["compression"]
             )
+        elif hub_custom_type == "bytes":
+            return base64.b64decode(obj["data"])
         return obj

{"golden_diff": "diff --git a/deeplake/util/json.py b/deeplake/util/json.py\n--- a/deeplake/util/json.py\n+++ b/deeplake/util/json.py\n@@ -201,6 +201,12 @@\n                 }\n             else:\n                 return self.default(obj.array)\n+        elif isinstance(obj, bytes):\n+            return {\n+                \"_hub_custom_type\": \"bytes\",\n+                \"data\": base64.b64encode(obj).decode(),\n+            }\n+\n         return obj\n \n \n@@ -218,4 +224,6 @@\n             return Sample(\n                 buffer=base64.b64decode(obj[\"data\"]), compression=obj[\"compression\"]\n             )\n+        elif hub_custom_type == \"bytes\":\n+            return base64.b64decode(obj[\"data\"])\n         return obj\n", "issue": "[BUG] Can't write objects to JSON\nv3.0.14\r\n\r\n```python\r\nimport pickle\r\nt = ds.create_tensor(f\"t/group/f\", htype=\"json\", chunk_compression=\"lz4\")\r\nt.append(pickle.dumps(\"test\"))  # pass any pickled object into append gets error\r\n```\r\n\r\n```\r\nValueError: Circular reference detected\r\n```\r\n\r\npassing strings and such into this tensor works fine, but for some reason any pickled object or python object that gets pickled gives the above ValueError.\n", "before_files": [{"content": "from typing import Any, Dict, List, Optional, Tuple, Union\nimport numpy as np\nfrom numpy import ndarray\nimport json\nimport base64\nfrom deeplake.core.sample import Sample  # type: ignore\n\nSchema = Any\n\n\nscalars = [\"int\", \"float\", \"bool\", \"str\", \"list\", \"dict\", \"ndarray\", \"Sample\"]\ntypes = [\"Any\", \"Dict\", \"List\", \"Optional\", \"Union\"]\n\n\ndef _norm_type(typ: str):\n    typ = typ.replace(\"typing.\", \"\")\n    replacements = {\n        \"numpy.ndarray\": \"ndarray\",\n        \"np.ndarray\": \"ndarray\",\n        \"deeplake.core.sample.Sample\": \"Sample\",\n        \"deeplake.Sample\": \"Sample\",\n    }\n    return replacements.get(typ, typ)\n\n\ndef _parse_schema(schema: Union[str, Schema]) -> Tuple[str, List[str]]:\n    if getattr(schema, \"__module__\", None) == \"typing\":\n        schema = str(schema)\n        validate = False\n    else:\n        validate = True\n\n    if schema in scalars:\n        return schema, []\n\n    if \"[\" not in schema:\n        return _norm_type(schema), []\n\n    typ, param_string = schema.split(\"[\", 1)\n    typ = _norm_type(typ)\n    assert param_string[-1] == \"]\"\n    params = []\n    buff = \"\"\n    level = 0\n    for c in param_string:\n        if c == \"[\":\n            level += 1\n            buff += c\n        elif c == \"]\":\n            if level == 0:\n                if buff:\n                    params.append(buff)\n                if validate:\n                    _validate_schema(typ, params)\n                return typ, params\n            else:\n                buff += c\n                level -= 1\n        elif c == \",\":\n            if level == 0:\n                params.append(buff)\n                buff = \"\"\n            else:\n                buff += c\n        elif c == \" \":\n            continue\n        else:\n            buff += c\n    raise InvalidJsonSchemaException()\n\n\nclass InvalidJsonSchemaException(Exception):\n    pass\n\n\nclass ArgumentMismatchException(InvalidJsonSchemaException):\n    def __init__(self, typ: str, actual: int, expected: int, exact: bool = False):\n        assert actual != expected\n        gt = actual > expected\n        super(ArgumentMismatchException, self).__init__(\n            f\"Too {'many' if gt else 'few'} parameters for {typ};\"\n            + f\" actual {actual},expected {'exatcly' if exact else ('at most' if gt else 'at least')} {expected}.\"\n        )\n\n\ndef _validate_schema(typ: str, params: List[str]) -> Tuple[str, List[str]]:\n    if typ in scalars:\n        return typ, params\n\n    if typ not in types:\n        raise InvalidJsonSchemaException(f\"Unsupported type: {typ}\")\n\n    def _err(expected_num_params: int, exact: bool = False):\n        raise ArgumentMismatchException(typ, len(params), expected_num_params, exact)\n\n    if typ == \"Any\":\n        if params:\n            _err(0)\n    elif typ == \"Optional\":\n        if len(params) > 1:\n            _err(1)\n    elif typ == \"Union\":\n        if len(params) == 0:\n            _err(1)\n    elif typ == \"List\":\n        if len(params) > 1:\n            _err(1)\n    elif typ == \"Dict\":\n        if len(params) not in (0, 2):\n            _err(2, True)\n    return typ, params\n\n\ndef _validate_any(obj: Any, params: List[str]):\n    assert not params\n    return True\n\n\ndef _validate_union(obj: Any, params: List[str]):\n    for schema in params:\n        if _validate_object(obj, schema):\n            return True\n    return False\n\n\ndef _validate_optional(obj: Any, params: List[str]) -> bool:\n    assert len(params) <= 1\n    if obj is None:\n        return True\n    if params:\n        return _validate_object(obj, params[0])\n    return True\n\n\ndef _validate_list(obj: Any, params: List[str]) -> bool:\n    assert len(params) <= 1\n    if not isinstance(obj, (list, tuple)):\n        return False\n    if params:\n        for item in obj:\n            if not _validate_object(item, params[0]):\n                return False\n    return True\n\n\ndef _validate_dict(obj: Any, params: List[str]) -> bool:\n    assert len(params) in (0, 2)\n    if not isinstance(obj, dict):\n        return False\n    if params:\n        assert params[0] in (\n            \"str\",\n            \"Any\",\n        ), \"Only string keys are allowed for json dicts.\"\n        for v in obj.values():\n            if not _validate_object(v, params[1]):\n                return False\n    return True\n\n\ndef _validate_nonetype(obj: Any, params: List[str]) -> bool:\n    assert not params\n    return obj is None\n\n\ndef _validate_object(obj: Any, schema: Union[str, Schema]) -> bool:\n    typ, params = _parse_schema(schema)\n    if typ in scalars:\n        return isinstance(obj, eval(typ))\n    return globals()[f\"_validate_{typ.lower()}\"](obj, params)\n\n\nclass JsonValidationError(Exception):\n    pass\n\n\ndef validate_json_object(obj: Any, schema: Union[str, Schema]) -> None:\n    if obj and not _validate_object(obj, schema):\n        raise JsonValidationError()\n\n\ndef validate_json_schema(schema: str):\n    _parse_schema(schema)\n\n\nclass HubJsonEncoder(json.JSONEncoder):\n    def default(self, obj):\n        if isinstance(obj, ndarray):\n            return {\n                \"_hub_custom_type\": \"ndarray\",\n                \"data\": base64.b64encode(obj.tobytes()).decode(),\n                \"shape\": obj.shape,\n                \"dtype\": obj.dtype.name,\n            }\n        elif isinstance(obj, Sample):\n            if obj.compression:\n                return {\n                    \"_hub_custom_type\": \"Sample\",\n                    \"data\": base64.b64encode(obj.buffer).decode(),\n                    \"compression\": obj.compression,\n                }\n            else:\n                return self.default(obj.array)\n        return obj\n\n\nclass HubJsonDecoder(json.JSONDecoder):\n    def __init__(self, *args, **kwargs):\n        json.JSONDecoder.__init__(self, object_hook=self.object_hook, *args, **kwargs)\n\n    def object_hook(self, obj):\n        hub_custom_type = obj.get(\"_hub_custom_type\")\n        if hub_custom_type == \"ndarray\":\n            return np.frombuffer(\n                base64.b64decode(obj[\"data\"]), dtype=obj[\"dtype\"]\n            ).reshape(obj[\"shape\"])\n        elif hub_custom_type == \"Sample\":\n            return Sample(\n                buffer=base64.b64decode(obj[\"data\"]), compression=obj[\"compression\"]\n            )\n        return obj\n", "path": "deeplake/util/json.py"}], "after_files": [{"content": "from typing import Any, Dict, List, Optional, Tuple, Union\nimport numpy as np\nfrom numpy import ndarray\nimport json\nimport base64\nfrom deeplake.core.sample import Sample  # type: ignore\n\nSchema = Any\n\n\nscalars = [\"int\", \"float\", \"bool\", \"str\", \"list\", \"dict\", \"ndarray\", \"Sample\"]\ntypes = [\"Any\", \"Dict\", \"List\", \"Optional\", \"Union\"]\n\n\ndef _norm_type(typ: str):\n    typ = typ.replace(\"typing.\", \"\")\n    replacements = {\n        \"numpy.ndarray\": \"ndarray\",\n        \"np.ndarray\": \"ndarray\",\n        \"deeplake.core.sample.Sample\": \"Sample\",\n        \"deeplake.Sample\": \"Sample\",\n    }\n    return replacements.get(typ, typ)\n\n\ndef _parse_schema(schema: Union[str, Schema]) -> Tuple[str, List[str]]:\n    if getattr(schema, \"__module__\", None) == \"typing\":\n        schema = str(schema)\n        validate = False\n    else:\n        validate = True\n\n    if schema in scalars:\n        return schema, []\n\n    if \"[\" not in schema:\n        return _norm_type(schema), []\n\n    typ, param_string = schema.split(\"[\", 1)\n    typ = _norm_type(typ)\n    assert param_string[-1] == \"]\"\n    params = []\n    buff = \"\"\n    level = 0\n    for c in param_string:\n        if c == \"[\":\n            level += 1\n            buff += c\n        elif c == \"]\":\n            if level == 0:\n                if buff:\n                    params.append(buff)\n                if validate:\n                    _validate_schema(typ, params)\n                return typ, params\n            else:\n                buff += c\n                level -= 1\n        elif c == \",\":\n            if level == 0:\n                params.append(buff)\n                buff = \"\"\n            else:\n                buff += c\n        elif c == \" \":\n            continue\n        else:\n            buff += c\n    raise InvalidJsonSchemaException()\n\n\nclass InvalidJsonSchemaException(Exception):\n    pass\n\n\nclass ArgumentMismatchException(InvalidJsonSchemaException):\n    def __init__(self, typ: str, actual: int, expected: int, exact: bool = False):\n        assert actual != expected\n        gt = actual > expected\n        super(ArgumentMismatchException, self).__init__(\n            f\"Too {'many' if gt else 'few'} parameters for {typ};\"\n            + f\" actual {actual},expected {'exatcly' if exact else ('at most' if gt else 'at least')} {expected}.\"\n        )\n\n\ndef _validate_schema(typ: str, params: List[str]) -> Tuple[str, List[str]]:\n    if typ in scalars:\n        return typ, params\n\n    if typ not in types:\n        raise InvalidJsonSchemaException(f\"Unsupported type: {typ}\")\n\n    def _err(expected_num_params: int, exact: bool = False):\n        raise ArgumentMismatchException(typ, len(params), expected_num_params, exact)\n\n    if typ == \"Any\":\n        if params:\n            _err(0)\n    elif typ == \"Optional\":\n        if len(params) > 1:\n            _err(1)\n    elif typ == \"Union\":\n        if len(params) == 0:\n            _err(1)\n    elif typ == \"List\":\n        if len(params) > 1:\n            _err(1)\n    elif typ == \"Dict\":\n        if len(params) not in (0, 2):\n            _err(2, True)\n    return typ, params\n\n\ndef _validate_any(obj: Any, params: List[str]):\n    assert not params\n    return True\n\n\ndef _validate_union(obj: Any, params: List[str]):\n    for schema in params:\n        if _validate_object(obj, schema):\n            return True\n    return False\n\n\ndef _validate_optional(obj: Any, params: List[str]) -> bool:\n    assert len(params) <= 1\n    if obj is None:\n        return True\n    if params:\n        return _validate_object(obj, params[0])\n    return True\n\n\ndef _validate_list(obj: Any, params: List[str]) -> bool:\n    assert len(params) <= 1\n    if not isinstance(obj, (list, tuple)):\n        return False\n    if params:\n        for item in obj:\n            if not _validate_object(item, params[0]):\n                return False\n    return True\n\n\ndef _validate_dict(obj: Any, params: List[str]) -> bool:\n    assert len(params) in (0, 2)\n    if not isinstance(obj, dict):\n        return False\n    if params:\n        assert params[0] in (\n            \"str\",\n            \"Any\",\n        ), \"Only string keys are allowed for json dicts.\"\n        for v in obj.values():\n            if not _validate_object(v, params[1]):\n                return False\n    return True\n\n\ndef _validate_nonetype(obj: Any, params: List[str]) -> bool:\n    assert not params\n    return obj is None\n\n\ndef _validate_object(obj: Any, schema: Union[str, Schema]) -> bool:\n    typ, params = _parse_schema(schema)\n    if typ in scalars:\n        return isinstance(obj, eval(typ))\n    return globals()[f\"_validate_{typ.lower()}\"](obj, params)\n\n\nclass JsonValidationError(Exception):\n    pass\n\n\ndef validate_json_object(obj: Any, schema: Union[str, Schema]) -> None:\n    if obj and not _validate_object(obj, schema):\n        raise JsonValidationError()\n\n\ndef validate_json_schema(schema: str):\n    _parse_schema(schema)\n\n\nclass HubJsonEncoder(json.JSONEncoder):\n    def default(self, obj):\n        if isinstance(obj, ndarray):\n            return {\n                \"_hub_custom_type\": \"ndarray\",\n                \"data\": base64.b64encode(obj.tobytes()).decode(),\n                \"shape\": obj.shape,\n                \"dtype\": obj.dtype.name,\n            }\n        elif isinstance(obj, Sample):\n            if obj.compression:\n                return {\n                    \"_hub_custom_type\": \"Sample\",\n                    \"data\": base64.b64encode(obj.buffer).decode(),\n                    \"compression\": obj.compression,\n                }\n            else:\n                return self.default(obj.array)\n        elif isinstance(obj, bytes):\n            return {\n                \"_hub_custom_type\": \"bytes\",\n                \"data\": base64.b64encode(obj).decode(),\n            }\n\n        return obj\n\n\nclass HubJsonDecoder(json.JSONDecoder):\n    def __init__(self, *args, **kwargs):\n        json.JSONDecoder.__init__(self, object_hook=self.object_hook, *args, **kwargs)\n\n    def object_hook(self, obj):\n        hub_custom_type = obj.get(\"_hub_custom_type\")\n        if hub_custom_type == \"ndarray\":\n            return np.frombuffer(\n                base64.b64decode(obj[\"data\"]), dtype=obj[\"dtype\"]\n            ).reshape(obj[\"shape\"])\n        elif hub_custom_type == \"Sample\":\n            return Sample(\n                buffer=base64.b64decode(obj[\"data\"]), compression=obj[\"compression\"]\n            )\n        elif hub_custom_type == \"bytes\":\n            return base64.b64decode(obj[\"data\"])\n        return obj\n", "path": "deeplake/util/json.py"}]}