Skip to content
This repository has been archived by the owner on Oct 14, 2024. It is now read-only.

Commit

Permalink
Merge pull request #243 from microsoft/fix/write-additional-data
Browse files Browse the repository at this point in the history
Fix/write additional data
  • Loading branch information
samwelkanda authored Mar 5, 2024
2 parents f615696 + d1b691b commit 326a0ce
Show file tree
Hide file tree
Showing 9 changed files with 75 additions and 39 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.1.0] - 2024-02-29

### Added

### Changed
- Support objects and collections when writing additional data.

## [1.0.1] - 2023-12-16

### Added
Expand Down
2 changes: 1 addition & 1 deletion kiota_serialization_json/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
VERSION: str = '1.0.1'
VERSION: str = '1.1.0'
4 changes: 2 additions & 2 deletions kiota_serialization_json/json_parse_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,11 +300,11 @@ def try_get_anything(self, value: Any) -> Any:
if isinstance(datetime_obj, pendulum.Duration):
return datetime_obj.as_timedelta()
return datetime_obj
except ValueError:
except:
pass
try:
return UUID(value)
except ValueError:
except:
pass
return value
raise ValueError(f"Unexpected additional value type {type(value)} during deserialization.")
Expand Down
1 change: 0 additions & 1 deletion kiota_serialization_json/json_parse_node_factory.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import json
from io import BytesIO

from kiota_abstractions.serialization import ParseNode, ParseNodeFactory

Expand Down
56 changes: 28 additions & 28 deletions kiota_serialization_json/json_serialization_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

T = TypeVar("T")
U = TypeVar("U", bound=Parsable)
PRIMITIVE_TYPES = [bool, str, int, float, UUID, datetime, timedelta, date, time, bytes, Enum]


class JsonSerializationWriter(SerializationWriter):
Expand Down Expand Up @@ -326,7 +327,7 @@ def write_additional_data_value(self, value: Dict[str, Any]) -> None:
"""
if isinstance(value, dict):
for key, val in value.items():
self.writer[key] = val
self.write_any_value(key, val)

def get_serialized_content(self) -> bytes:
"""Gets the value of the serialized content.
Expand Down Expand Up @@ -424,34 +425,33 @@ def write_any_value(self, key: Optional[str], value: Any) -> Any:
key (Optional[str]): The key to be used for the written value. May be null.
value Any): The value to be written.
"""
primitive_types = [bool, str, int, float, UUID, datetime, timedelta, date, time, Enum]
if value:
value_type = type(value)
if key:
if value_type in primitive_types:
method = getattr(self, f'write_{value_type.__name__.lower()}_value')
method(key, value)
elif isinstance(value, Parsable):
self.write_object_value(key, value)
elif hasattr(value, '__dict__'):
self.write_non_parsable_object_value(key, value)
else:
raise TypeError(
f"Encountered an unknown type during serialization {value_type} \
with key {key}"
)
value_type = type(value)
if value is None:
self.write_null_value(key)
elif value_type in PRIMITIVE_TYPES:
method = getattr(self, f'write_{value_type.__name__.lower()}_value')
method(key, value)
elif isinstance(value, Parsable):
self.write_object_value(key, value)
elif isinstance(value, list):
if all(isinstance(x, Parsable) for x in value):
self.write_collection_of_object_values(key, value)
elif all(isinstance(x, Enum) for x in value):
self.write_collection_of_enum_values(key, value)
elif all((type(x) in PRIMITIVE_TYPES) for x in value):
self.write_collection_of_primitive_values(key, value)
else:
if value_type in primitive_types:
method = getattr(self, f'write_{value_type.__name__.lower()}_value')
method(None, value)
elif isinstance(value, Parsable):
self.write_object_value(None, value)
elif hasattr(value, '__dict__'):
self.write_non_parsable_object_value(None, value)
else:
raise TypeError(
f"Encountered an unknown type during serialization {value_type}"
)
raise TypeError(
f"Encountered an unknown collection type during serialization \
{value_type} with key {key}"
)
elif hasattr(value, '__dict__'):
self.write_non_parsable_object_value(key, value)
else:
raise TypeError(
f"Encountered an unknown type during serialization {value_type} \
with key {key}"
)

def _serialize_value(self, temp_writer: JsonSerializationWriter, value: U):
if on_before := self.on_before_object_serialization:
Expand Down
4 changes: 2 additions & 2 deletions tests/helpers/user2.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
from datetime import date, datetime
from typing import Any, Callable, Dict, List, Optional, TypeVar

from kiota_abstractions.serialization import ParseNode, SerializationWriter
from kiota_abstractions.serialization import Parsable, ParseNode, SerializationWriter

T = TypeVar('T')


@dataclass
class User2():
class User2(Parsable):
additional_data: Dict[str, Any] = field(default_factory=dict)
id: Optional[int] = None
display_name: Optional[str] = None
Expand Down
8 changes: 7 additions & 1 deletion tests/unit/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ def user1_json():
'"birthday": "2000-09-04", '\
'"business_phones": ["+1 205 555 0108"], '\
'"mobile_phone": null, '\
'"is_active": true}'
'"is_active": true, '\
'"additional_data": {"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity", '\
'"manager": {"id": "8f841f30-e6e3-439a-a812-ebd369559c36", '\
'"updated_at": "2022-01-27T12:59:45.596117+00:00", "is_active": true}, '\
'"approvers": [{"id": "8f841f30-e6e3-439a-a812-ebd369559c36", '\
'"updated_at": "2022-01-27T12:59:45.596117+00:00", "is_active": true}, '\
'{"display_name": "John Doe", "age": 32}]}}'


@pytest.fixture
Expand Down
19 changes: 17 additions & 2 deletions tests/unit/test_json_parse_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
from uuid import UUID

import pytest

from pendulum import DateTime, FixedTimezone
from kiota_serialization_json.json_parse_node import JsonParseNode

from ..helpers import OfficeLocation, User

url: str = "https://graph.microsoft.com/v1.0/$metadata#users/$entity"
Expand Down Expand Up @@ -111,6 +110,22 @@ def test_get_object_value(user1_json):
assert result.business_phones == ["+1 205 555 0108"]
assert result.is_active is True
assert result.mobile_phone is None
assert result.additional_data["additional_data"]["@odata.context"] == "https://graph.microsoft.com/v1.0/$metadata#users/$entity"
assert result.additional_data["additional_data"]["manager"] == {
"id": UUID('8f841f30-e6e3-439a-a812-ebd369559c36'),
"updated_at": DateTime(2022, 1, 27, 12, 59, 45, 596117, tzinfo=FixedTimezone(0, name="+00:00")),
"is_active": True}
assert result.additional_data["additional_data"]["approvers"] == [
{
"id": UUID('8f841f30-e6e3-439a-a812-ebd369559c36'),
"updated_at": DateTime(2022, 1, 27, 12, 59, 45, 596117, tzinfo=FixedTimezone(0, name="+00:00")),
"is_active": True
},
{
"display_name": "John Doe",
"age": 32
}
]


def test_get_collection_of_object_values(users_json):
Expand Down
13 changes: 11 additions & 2 deletions tests/unit/test_json_serialization_writer.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from datetime import date
from uuid import UUID

import pytest
Expand Down Expand Up @@ -245,16 +246,24 @@ def test_write_null_value():
assert content_string == '{"mobilePhone": null}'


def test_write_additional_data_value():
def test_write_additional_data_value(user_1, user_2):
json_serialization_writer = JsonSerializationWriter()
json_serialization_writer.write_additional_data_value(
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity",
"businessPhones": ["+1 205 555 0108"],
"manager": user_1,
"approvers": [user_1, user_2],
"created_at": date(2022, 1, 27)
}
)
content = json_serialization_writer.get_serialized_content()
content_string = content.decode('utf-8')
assert content_string == '{"@odata.context": '\
'"https://graph.microsoft.com/v1.0/$metadata#users/$entity", '\
'"businessPhones": ["+1 205 555 0108"]}'
'"businessPhones": ["+1 205 555 0108"], '\
'"manager": {"id": "8f841f30-e6e3-439a-a812-ebd369559c36", '\
'"updated_at": "2022-01-27T12:59:45.596117+00:00", "is_active": true}, '\
'"approvers": [{"id": "8f841f30-e6e3-439a-a812-ebd369559c36", '\
'"updated_at": "2022-01-27T12:59:45.596117+00:00", "is_active": true}, '\
'{"display_name": "John Doe", "age": 32}], "created_at": "2022-01-27"}'

0 comments on commit 326a0ce

Please sign in to comment.