{"record":{"id":"75394db5ac0959c4","repo":"roboflow/supervision","slug":"object-of-type-type-value-name-is-not-json","errorCode":null,"errorMessage":"Object of type {type(value).__name__} is not JSON serializable","messagePattern":"Object of type (.+?) is not JSON serializable","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/supervision/detection/tools/json_sink.py","lineNumber":107,"sourceCode":"\n        Called as the ``default`` hook by :func:`json.dump`. Converts\n        :class:`numpy.generic` scalars via ``.item()`` and\n        :class:`numpy.ndarray` instances via ``.tolist()``.\n\n        Args:\n            value: Object the standard JSON encoder could not serialize.\n\n        Returns:\n            A Python scalar or nested list equivalent of ``value``.\n\n        Raises:\n            TypeError: If ``value`` is neither a NumPy scalar nor an ndarray.\n        \"\"\"\n        if isinstance(value, np.generic):\n            return value.item()\n        if isinstance(value, np.ndarray):\n            return value.tolist()\n        raise TypeError(\n            f\"Object of type {type(value).__name__} is not JSON serializable\"\n        )\n\n    def write_and_close(self) -> None:\n        \"\"\"\n        Write and close the JSON file.\n        \"\"\"\n        if self.file:\n            try:\n                json.dump(\n                    self.data, self.file, indent=4, default=JSONSink._json_default\n                )\n            finally:\n                self.file.close()\n\n    @staticmethod\n    def _slice_value(value: Any, i: int, n: int) -> Any:\n        \"\"\"","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/detection/tools/json_sink.py#L89-L125","documentation":"Raised by JSONSink's default serializer when json.dump encounters a value that is neither a np.generic scalar nor an np.ndarray. The hook exists specifically to convert NumPy types to plain Python; any other non-JSON-native object (datetime, dataclass, torch tensor, custom class) falls through to this TypeError.","triggerScenarios":"Appending data to JSONSink that contains a Python datetime/date, a torch.Tensor, a dataclass instance, a set, or any custom object — via sink.append(...) where one of the payload values is not JSON-native or NumPy.","commonSituations":"Logging detection metadata such as timestamps (datetime.now()), model objects, or tuples of custom classes alongside frame data; migrating from a sink that used str() coercion to JSONSink which does not.","solutions":["Convert non-NumPy objects before appending: str() or .isoformat() for datetimes, dataclasses.asdict() for dataclasses, .tolist() for torch tensors.","Restrict appended values to JSON-native types (str/int/float/bool/None/list/dict) plus NumPy scalars and arrays.","If you must keep arbitrary types, pre-serialize them yourself and store the string form."],"exampleFix":"# before\nsink.append(frame=1, at=datetime.now(), class_name='person')  # TypeError\n\n# after\nsink.append(frame=1, at=datetime.now().isoformat(), class_name='person')","handlingStrategy":"validation","validationCode":"import dataclasses\nimport datetime as dt\nimport numpy as np\n\ndef jsonable(v):\n    if isinstance(v, (dt.date, dt.datetime)):\n        return v.isoformat()\n    if isinstance(v, np.generic):\n        return v.item()\n    if isinstance(v, np.ndarray):\n        return v.tolist()\n    if dataclasses.is_dataclass(v):\n        return jsonable(dataclasses.asdict(v))\n    if hasattr(v, 'tolist'):\n        return v.tolist()\n    return v\n\nsink.append(**{k: jsonable(v) for k, v in payload.items()})","typeGuard":"def is_json_sink_safe(v) -> bool:\n    import dataclasses, datetime as dt\n    return v is None or isinstance(v, (str, int, float, bool, list, dict, np.generic, np.ndarray)) or isinstance(v, (dt.date, dt.datetime)) and False","tryCatchPattern":"try:\n    sink.append(frame=i, **payload)\nexcept TypeError as err:\n    if 'not JSON serializable' in str(err):\n        payload = {k: str(v) for k, v in payload.items()}\n        sink.append(frame=i, **payload)\n    else:\n        raise","preventionTips":["Convert timestamps to ISO strings and tensors to lists before appending.","Keep one project-wide to_jsonable() helper and route every sink payload through it."],"tags":["json-sink","serialization","numpy","typeerror","telemetry"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}