fix(json): only convert unambiguous date/datetime/UUID strings in additional data#664
Open
56badkarma wants to merge 1 commit into
Open
Conversation
…itional data try_get_anything ran every untyped string through five lenient parsers (datetime, UUID, timedelta, date, time). On Python 3.11+ this mangled ordinary text values landing in additional_data: "19-2026" became time(19, 0) at offset -20:26, "PT" became timedelta(0), "11.0" became time(11, 0), and 32-char hex strings became UUIDs. Round-tripping such records then persisted the mangled strings, corrupting user data. Only convert strings matching an anchored full ISO date/datetime shape or the canonical hyphenated UUID form, mirroring the .NET JsonParseNode which attempts strict DateTime/DateTimeOffset/Guid parses only. Date-only strings still parse through datetime_from_iso_format_compat, preserving the existing datetime result for real payload values. The previous four-digit and isdigit special cases are no longer needed since all-digit strings cannot match either pattern. Fixes microsoft#487 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019Uui4g7E7UmzKRGHMW5zbH
|
Author
|
@microsoft-github-policy-service agree |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Overview
JsonParseNode.try_get_anythingruns every untyped string (everything landing inadditional_data) through five lenient parsers in sequence:datetime_from_iso_format_compat,UUID,parse_timedelta_string,date.fromisoformat,time_from_iso_format_compat. On Python 3.11+ the lenient parsers accept many ordinary text values:This is not just a display problem: in our production SharePoint AP-invoicing app, invoice numbers like
19-2026were coerced totimeobjects, later stringified on update, and persisted back — permanently corrupting stored data (details with a captured wire payload in microsoftgraph/msgraph-sdk-python#1340).This PR replaces the speculative parsing with two anchored patterns, mirroring the .NET
JsonParseNode.TryGetAnything, which only attempts strictDateTime/DateTimeOffset/Guidparses and otherwise returns the string:^\d{4}-\d{2}-\d{2}([Tt ]\d{2}:\d{2}|$)) →datetime_from_iso_format_compatUUIDBehavior is unchanged for real payload values: full ISO datetimes still become
datetime, date-only strings still becomedatetime(same as today, via the same compat parser), canonical UUIDs still becomeUUID. Thetimedelta/timeguessing is removed entirely — Graph does not send bare durations or times as untyped strings, and their grammars overlap with too much real-world text. The__is_four_digit_number/isdigit()special cases (added for earlier symptom reports like microsoftgraph/msgraph-sdk-python#653) become unnecessary since all-digit strings cannot match either anchored pattern, and are removed.Related Issue
Fixes #487
Addresses microsoftgraph/msgraph-sdk-python#1340 and microsoftgraph/msgraph-sdk-python#653
Notes
timedelta/time/unhyphenated-UUID will now stay strings inadditional_data. That is the intent of the fix, but callers who relied on those accidental conversions would see a change; typed model fields are unaffected (they go through declared field deserializers and never reachtry_get_anything).Created/Modifieddatetimes still parse.Testing Instructions
cd packages/serialization/json && pytest tests/test_get_anything_does_not_coerce_text_valuescovers each reported corruption pattern (19-2026,PT,10:30,23.085,11.0, 32-hex, date fragments)datetime, canonical UUID →UUID; existing tests cover full ISO datetimes🤖 Generated with Claude Code
https://claude.ai/code/session_019Uui4g7E7UmzKRGHMW5zbH