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

Fix Numeric strings being converted to Datetime objects #348

Merged
merged 11 commits into from
Aug 23, 2024
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ 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.4.0] - 2024-08-23

### Added

- Fixed 4-digit numeric strings from being parsed as Datetime objects to being parsed as strings.


## [1.3.0] - 2024-07-26

### 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.3.0'
VERSION: str = '1.4.0'
11 changes: 10 additions & 1 deletion kiota_serialization_json/json_parse_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
from uuid import UUID

import pendulum
import re

from kiota_abstractions.serialization import Parsable, ParsableFactory, ParseNode

T = TypeVar("T")
Expand Down Expand Up @@ -291,6 +293,10 @@ def _assign_field_values(self, item: U) -> None:
deserialize but the model doesn't support additional data"
)

def is_four_digit_number(self, value: str) -> bool:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just making sure this method is not accessible from outside of the class?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's an instance method, and we really just need it here in the entire project, so nope, not accessible outside the class

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't it start with __ ?

pattern = r'^\d{4}$'
return bool(re.match(pattern, value))

def try_get_anything(self, value: Any) -> Any:
if isinstance(value, (int, float, bool)) or value is None:
return value
Expand All @@ -300,11 +306,14 @@ def try_get_anything(self, value: Any) -> Any:
return dict(map(lambda x: (x[0], self.try_get_anything(x[1])), value.items()))
if isinstance(value, str):
try:
if self.is_four_digit_number(value):
return value
baywet marked this conversation as resolved.
Show resolved Hide resolved

datetime_obj = pendulum.parse(value)
if isinstance(datetime_obj, pendulum.Duration):
return datetime_obj.as_timedelta()
return datetime_obj
except:
except ValueError:
pass
try:
return UUID(value)
Expand Down
18 changes: 18 additions & 0 deletions tests/unit/test_json_parse_node.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json
from datetime import date, datetime, time, timedelta
from uuid import UUID
import pendulum

import pytest
from pendulum import DateTime, FixedTimezone
Expand Down Expand Up @@ -54,17 +55,20 @@ def test_get_float_value(value: int):
assert isinstance(result, float)
assert result == float(value)


def test_get_uuid_value():
parse_node = JsonParseNode("f58411c7-ae78-4d3c-bb0d-3f24d948de41")
result = parse_node.get_uuid_value()
assert result == UUID("f58411c7-ae78-4d3c-bb0d-3f24d948de41")


@pytest.mark.parametrize("value", ["", " ", " ", "2022-01-0"])
def test_get_datetime_value_returns_none_with_invalid_str(value: str):
parse_node = JsonParseNode(value)
result = parse_node.get_datetime_value()
assert result is None


def test_get_datetime_value():
parse_node = JsonParseNode('2022-01-27T12:59:45.596117')
result = parse_node.get_datetime_value()
Expand Down Expand Up @@ -130,6 +134,20 @@ def test_get_enum_value_for_key_not_found():
assert result is None


def test_get_anythin_does_not_convert_numeric_chars_to_datetime():
parse_node = JsonParseNode("1212")
result = parse_node.try_get_anything("1212")
assert isinstance(result, str)
assert result == "1212"


def test_get_anythin_does_convert_date_string_to_datetime():
parse_node = JsonParseNode("2023-10-05T14:48:00.000Z")
result = parse_node.try_get_anything("2023-10-05T14:48:00.000Z")
assert isinstance(result, pendulum.DateTime)
assert result == pendulum.parse("2023-10-05T14:48:00.000Z")


def test_get_object_value(user1_json):
parse_node = JsonParseNode(json.loads(user1_json))
result = parse_node.get_object_value(User)
Expand Down
Loading