From 1339fda597915e8a06452779ddb9d7d3032fa445 Mon Sep 17 00:00:00 2001 From: b84330808 Date: Sun, 25 Oct 2026 16:20:57 +0900 Subject: [PATCH] Read GeoJson files as UTF-8 regardless of locale GeoJson(filename) opened the file in text mode without an encoding, so it was decoded with the locale encoding. On Windows that garbles or fails on non-ASCII properties (the bundled kuntarajat.geojson raises UnicodeDecodeError under cp932). Read the file as bytes and let json detect the encoding, which also accepts a UTF-8 BOM. Co-Authored-By: Claude Opus 5.5 --- folium/features.py | 6 ++++-- tests/test_features.py | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/folium/features.py b/folium/features.py index 587f5e053b..1638920697 100644 --- a/folium/features.py +++ b/folium/features.py @@ -757,8 +757,10 @@ def process_data(self, data: Any) -> dict: else: # This is a filename if not self.embed: self.embed_link = data - with open(data) as f: - return json.loads(f.read()) + # Read bytes so json can detect the encoding (UTF-8 per RFC 7946) + # instead of decoding with the platform's locale encoding. + with open(data, "rb") as f: + return json.load(f) elif hasattr(data, "__geo_interface__"): self.embed = True if hasattr(data, "to_crs"): diff --git a/tests/test_features.py b/tests/test_features.py index e41e0e8337..c05d57c7f1 100644 --- a/tests/test_features.py +++ b/tests/test_features.py @@ -232,6 +232,24 @@ def test_geojson_tooltip(): ), "GeoJsonTooltip GeometryCollection test failed." +@pytest.mark.parametrize("encoding", ["utf-8", "utf-8-sig"]) +def test_geojson_from_utf8_file(tmp_path, encoding): + data = { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": {"name": "東京都", "alt": "Hämeenlinna"}, + "geometry": {"type": "Point", "coordinates": [139.69, 35.69]}, + } + ], + } + path = tmp_path / "data.geojson" + path.write_text(json.dumps(data, ensure_ascii=False), encoding=encoding) + + assert GeoJson(str(path)).data == data + + # GeoJsonMarker type validation. def test_geojson_marker(): m = folium.Map([30.4, -97.5], zoom_start=10)