.Net: Fix #14021: Prune unannotated POCO properties from Redis JSON payloads#14045
Open
summitbaj wants to merge 3 commits into
Open
.Net: Fix #14021: Prune unannotated POCO properties from Redis JSON payloads#14045summitbaj wants to merge 3 commits into
summitbaj wants to merge 3 commits into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR ensures Redis JSON payloads only include properties that are part of the vector data model, excluding unannotated properties like NotAnnotated, and updates tests accordingly.
Changes:
- Filter out non-model properties during
MapFromDataToStorageModelinRedisJsonMapper. - Add assertions in mapper unit tests to ensure unannotated properties are excluded.
- Update Redis JSON collection tests’ expected JSON payloads to omit
NotAnnotatedand remove the related TODO.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| dotnet/src/VectorData/Redis/RedisJsonMapper.cs | Filters serialized JSON to retain only allowed model-backed storage property names. |
| dotnet/test/VectorData/Redis.UnitTests/RedisJsonMapperTests.cs | Adds assertions verifying unannotated properties are not included. |
| dotnet/test/VectorData/Redis.UnitTests/RedisJsonCollectionTests.cs | Updates expected JSON strings to exclude NotAnnotated and removes the outdated TODO. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+308
to
+311
| [InlineData(true, true, """{"data1_json_name":"data 1","data2":"data 2","vector1_json_name":[1,2,3,4],"vector2":[1,2,3,4]}""")] | ||
| [InlineData(true, false, """{"data1_json_name":"data 1","Data2":"data 2","vector1_json_name":[1,2,3,4],"Vector2":[1,2,3,4]}""")] | ||
| [InlineData(false, true, """{"data1_json_name":"data 1","data2":"data 2","vector1_json_name":[1,2,3,4],"vector2":[1,2,3,4]}""")] | ||
| [InlineData(false, false, """{"data1_json_name":"data 1","Data2":"data 2","vector1_json_name":[1,2,3,4],"Vector2":[1,2,3,4]}""")] |
…e failure diagnostics and remove null-conditionals
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.
Motivation and Context
Resolves #14021
Currently, when the .NET RedisJsonCollection upserts data, the RedisJsonMapper serializes the provided POCO into a
JsonNodeusingJsonSerializerOptions. BecauseJsonSerializerserializes all public properties by default, any POCO properties not uniquely annotated with[VectorStoreData]or[VectorStoreVector]inadvertently leak into the serialized JSON payload and are sent to Redis.Description
This PR addresses the serialization leak by implementing an explicit allow-list pruning phase within the mapper:
_allowedStorageNamesHashSetis populated inside RedisJsonMapper using theStorageNameof all annotatedDataPropertiesandVectorPropertiesfrom the active schema.JsonSerializer.SerializeToNode()completes, we evaluate the top-level keys. Any unannotated keys absent from the allow-list are dynamically scrubbed viajsonNode.Remove().By serializing the full POCO first and conditionally dropping keys, we safely preserve all of the user's custom
System.Text.Jsonsettings (naming policies, custom converters, etc.) without mutating their global resolver caching or forcing them to pollute their POCOs with global[JsonIgnore]attributes.Testing of the Changes
notAnnotated/NotAnnotatedmock returns, as well as the original// TODOcomments documenting the JSON leak.Assert.False(jsonObject!.ContainsKey("NotAnnotated"))to RedisJsonMapperTests to guarantee isolated test coverage against future regressions mapping MultiPropsModel.dotnet testreturned 109/109 success).