-
Notifications
You must be signed in to change notification settings - Fork 10.4k
Respect JsonSerializerOptions casing for property names in validation errors #62036
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…ation errors Co-authored-by: captainsafia <1857993+captainsafia@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good start! Left some comments inline.
src/Http/Http.Abstractions/test/Validation/ValidateContextTests.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: captainsafia <1857993+captainsafia@users.noreply.github.com>
I've addressed all the inline comments. Made the SerializerOptions property internal, removed the test file, and updated ValidationEndpointFilterFactory to use the internal property via reflection. All changes in commit 216406a. |
… from service provider Co-authored-by: captainsafia <1857993+captainsafia@users.noreply.github.com>
@captainsafia Unfortunately I hit an unexpected error while processing your comment. I've automatically reported this to GitHub. You can ask me to try again later by mentioning me in a new comment. If you want to contact GitHub about this error, please mention the following identifier so they can better serve you: Sorry for the inconvenience! |
@copilot Let's try to address the review comments I left for you earlier. You were on the right track with making the |
… complex keys Co-authored-by: captainsafia <1857993+captainsafia@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're almost there! One more comment. Also, be undo all the changes you made to the package.json
files and remove the package.json.bak
files.
…tions Co-authored-by: captainsafia <1857993+captainsafia@users.noreply.github.com>
@copilot Revert any changes made to package.json and package-lock.json files to their state in main. |
@copilot I've made some fixes to the implementation and want you to follow up on some things, including:
|
Co-authored-by: captainsafia <1857993+captainsafia@users.noreply.github.com>
I've implemented both performance improvements in commit 409bb34:
Warning Firewall rules blocked me from connecting to one or more addressesI tried to connect to the following addresses, but was blocked by firewall rules:If you need me to access, download, or install something from one of these locations, you can either:
|
src/Http/Http.Abstractions/src/Validation/ValidatableParameterInfo.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: captainsafia <1857993+captainsafia@users.noreply.github.com>
Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details. Warning Firewall rules blocked me from connecting to one or more addressesI tried to connect to the following addresses, but was blocked by firewall rules:If you need me to access, download, or install something from one of these locations, you can either:
|
4afa2bb
to
f035b35
Compare
@DeagleGross @BrennanConroy Would love your review n this PR. Outside of the prompting, I ended up making local changes on Some things here:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great! I can't say I understand how this works but just looking at the changes to the expected results of the tests, this is a very welcome change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- We need to add
JsonSerializerOptions
as a property on theValidateContext
since we don't have access to theJsonOptions
type in theHttp.Abstractions
assembly in order to be able to resolve it ourselves in the ValidatableTypes. I think that probably makes the most sense for frameworks who are building on top of the abstractions API anyways.
Would this be better on ValidationOptions? We could use IPostConfigureOptions to set it once.
We should also create an API proposal issue for it. I bet copilot would do well at taking our issue template and this PR as inputs and creating an issue.
- The precedence ordering is
[Display(Name = "")]
, then[JsonPropertyName]
then the JSON naming policy.
Does [Display(Name = "")]
affect how the type gets serialized? And if not, shouldn't the validation errors match what gets serialized?
Also, do we have a test that verifies what happens when you have both [Display(Name = "")]
and [JsonPropertyName]
on the same property?
@@ -106,9 +106,17 @@ public virtual async Task ValidateAsync(object? value, ValidateContext context, | |||
// Create a validation error for each member name that is provided | |||
foreach (var memberName in validationResult.MemberNames) | |||
{ | |||
// Format the member name using JsonSerializerOptions naming policy if available | |||
// Note: we don't respect [JsonPropertyName] here because we have no context of the property being validated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this true? It's not like we're asking for the one and only [JsonPropertyName] used for the type represented by the ValidatableTypeInfo here. That would be impossible. Instead, we're asking for the [JsonPropertyName] for each of its member properties, right? If we didn't have any context of the property being validated here, how are we getting the name of the property at all let alone the proper casing?
I think we should probably respect all the same attributes we do in ValidatablePropertyInfo, namely [Display] (if we keep doing that) and [JsonPropertyName].
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this just redundant? Could it be that memberName already formatted here? I haven't run it, so it might not be the case, but we should definitely add some tests with a camel cased PropertyNamingPolicy and a capitalized first letter in the [JsonPropertyName] attribute.
public string? LastName { get; set; } | ||
} | ||
|
||
[Fact] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Fact] | |
[Fact] |
|
||
// Cache the HasDisplayAttribute result to avoid repeated reflection calls | ||
var property = DeclaringType.GetProperty(Name); | ||
_hasDisplayAttribute = property is not null && HasDisplayAttribute(property); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feels weird to grab the attribute, but then never actually use the value from the attribute. At that point, why not just use string.IsNullOrEmpty(DisplayName)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. I find it sometimes helps to ask copilot not to add any fields if you don't think it should be necessary.
/// When available, property names in validation errors will be formatted according to the | ||
/// PropertyNamingPolicy and JsonPropertyName attributes. | ||
/// </summary> | ||
public JsonSerializerOptions? SerializerOptions { get; set; } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Putting it on the record that I'm not a fan of adding this to the ValidateContext
. Especially if we're wanting to eventually move this API into dotnet/runtime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about moving it to ValidationOptions as I suggest here?
|
||
/// <summary> | ||
/// Creates a new instance of <see cref="ValidatablePropertyInfo"/>. | ||
/// </summary> | ||
protected ValidatablePropertyInfo( | ||
[param: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] | ||
[param: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicConstructors)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this necessary?
Summary
When configuring JSON serialization options with a custom property naming policy (like camelCase), validation error responses were not consistently following the same naming policy for property names. This created a disconnect between what clients send/expect and what the validation errors contained.
The implemented changes ensure validation errors respect the configured JSON naming policy, making them consistent with the rest of the API's JSON formatting.
Changes
SerializerOptions
property toValidateContext
to access JSON naming policiesValidationEndpointFilterFactory
to pass the JSON options from DI to the validation contextPropertyNamingPolicy
for error key namesitems[0].productName
→items[0].productName
)Before
After
The implementation preserves the full compatibility with existing usage while ensuring that property names in validation errors now follow the configured naming policy.
Fixes #61764.
Warning
Firewall rules blocked me from connecting to one or more addresses
I tried to connect to the following addresses, but was blocked by firewall rules:
cdn.fwupd.org
/usr/bin/fwupdmgr refresh
(dns block)If you need me to access, download, or install something from one of these locations, you can either:
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.