diff --git a/CHANGES.md b/CHANGES.md index 9265882d0..b954d4b3f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -22,6 +22,7 @@ * Use `@attrs.define` instead of dataclass for factories **breaking change** * Use `@attrs.define` instead of dataclass for factory extensions **breaking change** +* Handle `numpy` types in JSON/GeoJSON response ### titiler.core diff --git a/src/titiler/core/titiler/core/resources/responses.py b/src/titiler/core/titiler/core/resources/responses.py index cd37a6a85..3a99d6be5 100644 --- a/src/titiler/core/titiler/core/resources/responses.py +++ b/src/titiler/core/titiler/core/resources/responses.py @@ -2,6 +2,7 @@ from typing import Any +import numpy import simplejson as json from starlette import responses @@ -12,6 +13,16 @@ class XMLResponse(responses.Response): media_type = "application/xml" +class NumpyEncoder(json.JSONEncoder): + """Custom JSON Encoder.""" + + def default(self, obj): + """Catch numpy types and convert them.""" + if isinstance(obj, (numpy.ndarray, numpy.generic)): + return obj.tolist() + return super().default(obj) + + class JSONResponse(responses.JSONResponse): """Custom JSON Response.""" @@ -27,6 +38,7 @@ def render(self, content: Any) -> bytes: indent=None, ignore_nan=True, separators=(",", ":"), + cls=NumpyEncoder, ).encode("utf-8")