From f3696adade847b8777058bc8f875fd5aa22e6afe Mon Sep 17 00:00:00 2001 From: Zelys Date: Mon, 29 Jun 2026 13:57:10 -0500 Subject: [PATCH 1/2] fix(json): base64-decode bytes values on deserialization JsonParseNode._get_bytes_value() was encoding the raw base64 string as UTF-8 bytes instead of decoding it. Edm.Binary values in OData JSON are transmitted as base64 strings, so the correct behaviour is to call base64.b64decode() to recover the original bytes. The non-string path (json.dumps fallback) is also removed: the OData JSON spec only represents binary values as base64 strings, so passing a non-string to get_bytes_value() is not a valid call and now returns None. Fixes #636 --- .../kiota_serialization_json/json_parse_node.py | 11 +++-------- .../json/tests/unit/test_json_parse_node.py | 14 ++++++++++---- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/packages/serialization/json/kiota_serialization_json/json_parse_node.py b/packages/serialization/json/kiota_serialization_json/json_parse_node.py index c8a01669..898b6d02 100644 --- a/packages/serialization/json/kiota_serialization_json/json_parse_node.py +++ b/packages/serialization/json/kiota_serialization_json/json_parse_node.py @@ -1,5 +1,6 @@ from __future__ import annotations +import base64 import json import re import warnings @@ -290,15 +291,9 @@ def _get_time_value(value: Any) -> Optional[time]: @staticmethod def _get_bytes_value(value: Any) -> Optional[bytes]: - # if the node is a string, we need to decode it - # This ensures that the string is properly converted to bytes if isinstance(value, str): - base64_string = value - else: - base64_string = json.dumps(value) - if not base64_string: - return None - return base64_string.encode("utf-8") + return base64.b64decode(value) + return None @property def on_before_assign_field_values(self) -> Optional[Callable[[Parsable], None]]: diff --git a/packages/serialization/json/tests/unit/test_json_parse_node.py b/packages/serialization/json/tests/unit/test_json_parse_node.py index 18ac2c9c..6b194655 100644 --- a/packages/serialization/json/tests/unit/test_json_parse_node.py +++ b/packages/serialization/json/tests/unit/test_json_parse_node.py @@ -1,3 +1,4 @@ +import base64 import json from datetime import date, datetime, time, timedelta, timezone from uuid import UUID @@ -120,14 +121,19 @@ def test_get_collection_of_primitive_values_no_type(): def test_get_bytes_value(): parse_node = JsonParseNode("U2Ftd2VsIGlzIHRoZSBiZXN0") result = parse_node.get_bytes_value() - assert isinstance(result, bytes) - assert result.decode("utf-8") == "U2Ftd2VsIGlzIHRoZSBiZXN0" + assert result == b"Samwel is the best" -def test_get_bytes_json_compatible(): +def test_get_bytes_value_empty_string(): + parse_node = JsonParseNode("") + result = parse_node.get_bytes_value() + assert result == b"" + + +def test_get_bytes_value_non_string_returns_none(): parse_node = JsonParseNode({"test": 1}) result = parse_node.get_bytes_value() - assert json.loads(result.decode("utf-8")) == {"test": 1} + assert result is None def test_get_collection_of_enum_values(): From 9bbe79b96acda25762c77eed2f10cb67c5793eaa Mon Sep 17 00:00:00 2001 From: Zelys Date: Tue, 30 Jun 2026 12:10:05 -0500 Subject: [PATCH 2/2] fix(test): remove unused base64 import --- packages/serialization/json/tests/unit/test_json_parse_node.py | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/serialization/json/tests/unit/test_json_parse_node.py b/packages/serialization/json/tests/unit/test_json_parse_node.py index 6b194655..0b09ddc0 100644 --- a/packages/serialization/json/tests/unit/test_json_parse_node.py +++ b/packages/serialization/json/tests/unit/test_json_parse_node.py @@ -1,4 +1,3 @@ -import base64 import json from datetime import date, datetime, time, timedelta, timezone from uuid import UUID