Skip to content

.Net: Fix #14021: Prune unannotated POCO properties from Redis JSON payloads#14045

Open
summitbaj wants to merge 3 commits into
microsoft:mainfrom
summitbaj:fix-14021-redis-upsert-properties
Open

.Net: Fix #14021: Prune unannotated POCO properties from Redis JSON payloads#14045
summitbaj wants to merge 3 commits into
microsoft:mainfrom
summitbaj:fix-14021-redis-upsert-properties

Conversation

@summitbaj
Copy link
Copy Markdown

Motivation and Context

Resolves #14021

Currently, when the .NET RedisJsonCollection upserts data, the RedisJsonMapper serializes the provided POCO into a JsonNode using JsonSerializerOptions. Because JsonSerializer serializes 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:

  1. Pre-computed Allow-List: An _allowedStorageNames HashSet is populated inside RedisJsonMapper using the StorageName of all annotated DataProperties and VectorProperties from the active schema.
  2. Payload Pruning: During MapFromDataToStorageModel, after JsonSerializer.SerializeToNode() completes, we evaluate the top-level keys. Any unannotated keys absent from the allow-list are dynamically scrubbed via jsonNode.Remove().

By serializing the full POCO first and conditionally dropping keys, we safely preserve all of the user's custom System.Text.Json settings (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

  • I updated RedisJsonCollectionTests.cs to remove the hardcoded notAnnotated / NotAnnotated mock returns, as well as the original // TODO comments documenting the JSON leak.
  • I added Assert.False(jsonObject!.ContainsKey("NotAnnotated")) to RedisJsonMapperTests to guarantee isolated test coverage against future regressions mapping MultiPropsModel.
  • Validated locally using .NET 10 SDK (dotnet test returned 109/109 success).

Copilot AI review requested due to automatic review settings May 30, 2026 04:48
@summitbaj summitbaj requested a review from a team as a code owner May 30, 2026 04:48
@moonbox3 moonbox3 added the .NET Issue or Pull requests regarding .NET code label May 30, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

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 MapFromDataToStorageModel in RedisJsonMapper.
  • Add assertions in mapper unit tests to ensure unannotated properties are excluded.
  • Update Redis JSON collection tests’ expected JSON payloads to omit NotAnnotated and 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 thread dotnet/src/VectorData/Redis/RedisJsonMapper.cs
Comment thread dotnet/test/VectorData/Redis.UnitTests/RedisJsonCollectionTests.cs Outdated
Comment thread dotnet/test/VectorData/Redis.UnitTests/RedisJsonMapperTests.cs Outdated
@github-actions github-actions Bot changed the title Fix #14021: Prune unannotated POCO properties from Redis JSON payloads .Net: Fix #14021: Prune unannotated POCO properties from Redis JSON payloads May 30, 2026
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Automated Code Review

Reviewers: 4 | Confidence: 93% | Result: All clear

Reviewed: Correctness, Security Reliability, Test Coverage, Design Approach


Automated review by summitbaj's agents

@summitbaj summitbaj requested a review from Copilot May 30, 2026 05:19
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

Comment thread dotnet/test/VectorData/Redis.UnitTests/RedisJsonMapperTests.cs Outdated
Comment thread dotnet/test/VectorData/Redis.UnitTests/RedisJsonMapperTests.cs Outdated
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

.NET Issue or Pull requests regarding .NET code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

.Net: Bug: .NET: RedisJsonCollection JSON upsert includes unannotated POCO properties

3 participants