-
Notifications
You must be signed in to change notification settings - Fork 10k
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
Remove (Http)(Validation)ProblemDetails converters #44132
Comments
Background and MotivationAfter investigation, based on the aspnetcore/src/Shared/ProblemDetails/ProblemDetailsJsonConverter.cs Lines 13 to 17 in b02a2f1
While it is almost every time the expected behavior, as stated in the issue, the developers should be able to have the chance to configure the Also, the introduction of the converters (#12216), 3 years ago, was decided to work around the missing In this proposal, I am suggesting the removal of the internal S.T.J This should be just an implementation change, however, while is technically possible to serialize/deserialize a property with private setter with S.T.J we will get the SYSLIB1038: System.Text.Json source generator encountered a property annotated with [JsonInclude] but with inaccessible accessors warning/error when using S.T.J source generation. Proposed APInamespace Microsoft.AspNetCore.Mvc;
-[JsonConverter(typeof(ValidationProblemDetailsJsonConverter))]
public class ValidationProblemDetails : HttpValidationProblemDetails
{
- public new IDictionary<string, string[]> Errors => base.Errors;
+ public new IDictionary<string, string[]> Errors { get { return base.Errors; } set { base.Errors = value; } }
}
-[JsonConverter(typeof(ProblemDetailsJsonConverter))]
public class ProblemDetails
{
- [JsonPropertyName("type")]
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Type { get; set; }
- [JsonPropertyName("title")]
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Title { get; set; }
- [JsonPropertyName("status")]
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public int? Status { get; set; }
- [JsonPropertyName("detail")]
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Detail { get; set; }
- [JsonPropertyName("instance")]
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Instance { get; set; }
- public IDictionary<string, object?> Extensions { get; } = new Dictionary<string, object?>(StringComparer.Ordinal);
+ public IDictionary<string, object?> Extensions { get; set; } = new Dictionary<string, object?>(StringComparer.Ordinal);
}
namespace Microsoft.AspNetCore.Http;
-[JsonConverter(typeof(HttpValidationProblemDetailsJsonConverter))]
public class HttpValidationProblemDetails : ProblemDetails
{
- public IDictionary<string, string[]> Errors { get; } = new Dictionary<string, string[]>(StringComparer.Ordinal);
+ public IDictionary<string, string[]> Errors { get; set; } = new Dictionary<string, string[]>(StringComparer.Ordinal);
} Usage ExamplesAs a side effect of making the properties var problem = new HttpValidationProblemDetails();
problem.Extensions = new Dictionary<string, object>()
{
["ext"] = "ext-value"
};
problem.Errors = new Dictionary<string, string[]>
{
["key0"] = new string[] { "error" }
}; Not part of the API change itself but since we are removing the Converters users will be able to include all ProblemDetails types as part of [JsonSerializable(typeof(ProblemDetails))]
[JsonSerializable(typeof(ValidationProblemDetails))]
[JsonSerializable(typeof(HttpValidationProblemDetails))]
public partial class TestContext : JsonSerializerContext
{
} |
Thanks for contacting us. We're moving this issue to the |
Just came across this. There is a separate json option Due to special way I think I could just derive from My current not ideal workaround:
|
IMO, the right thing to do for |
Thank you for submitting this for API review. This will be reviewed by @dotnet/aspnet-api-review at the next meeting of the ASP.NET Core API Review group. Please ensure you take a look at the API review process documentation and ensure that:
|
API Review notes:
@brunolins16 Can you double check if the setters are still absolutely necessary? If so, why? |
@halter73 I have tested and still the same warning when I followed what is documented here Non-public property accessors, the usage of non-public property accessors is not supported unless when using the
I can see the red squiggles, or an explicitly exception thrown (probably the setter is not even used) in the source gen'd code, however, it successfully compiles, and the deserialization works. Maybe someone from @dotnet/area-system-text-json can help us to understand if it is absolutely necessary. Sample: https://github.com/brunolins16/problemdetails-sourcegen |
Your example happens to work because you're prepopulating the dictionary on the property. If I change the POCO to public class ProblemDetails
{
[JsonExtensionData]
[JsonInclude]
public IDictionary<string, object>? MyProperty { get; } = null;
} Then your app will immediately hit the exception produced by the source generator. The function of |
@halter73 I believe we need to follow with what I proposed originally and add the public setter as recommended. |
Thank you for submitting this for API review. This will be reviewed by @dotnet/aspnet-api-review at the next meeting of the ASP.NET Core API Review group. Please ensure you take a look at the API review process documentation and ensure that:
|
API Review Notes:
Let's get rid of these JsonConverters! We can revisit removing the setters if we get an S.T.J update that doesn't require it, but it doesn't seem too bad either way. API Approved! namespace Microsoft.AspNetCore.Mvc;
-[JsonConverter(typeof(ValidationProblemDetailsJsonConverter))]
public class ValidationProblemDetails : HttpValidationProblemDetails
{
- public new IDictionary<string, string[]> Errors => base.Errors;
+ public new IDictionary<string, string[]> Errors { get { return base.Errors; } set { base.Errors = value; } }
}
-[JsonConverter(typeof(ProblemDetailsJsonConverter))]
public class ProblemDetails
{
- [JsonPropertyName("type")]
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Type { get; set; }
- [JsonPropertyName("title")]
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Title { get; set; }
- [JsonPropertyName("status")]
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public int? Status { get; set; }
- [JsonPropertyName("detail")]
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Detail { get; set; }
- [JsonPropertyName("instance")]
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Instance { get; set; }
- public IDictionary<string, object?> Extensions { get; } = new Dictionary<string, object?>(StringComparer.Ordinal);
+ public IDictionary<string, object?> Extensions { get; set; } = new Dictionary<string, object?>(StringComparer.Ordinal);
}
namespace Microsoft.AspNetCore.Http;
-[JsonConverter(typeof(HttpValidationProblemDetailsJsonConverter))]
public class HttpValidationProblemDetails : ProblemDetails
{
- public IDictionary<string, string[]> Errors { get; } = new Dictionary<string, string[]>(StringComparer.Ordinal);
+ public IDictionary<string, string[]> Errors { get; set; } = new Dictionary<string, string[]>(StringComparer.Ordinal);
} |
Hi, I think this may be related, but the casing for ProblemDetails is also inconsistent. ProblemDetails itself defaults to camel case, but as you can see above when describing the "Summary" field, it's capitalized. Shouldn't that be lower case, assuming @TanvirArjel is using the default naming policy?
I've also noticed ProblemDetails does not obey
JsonOptions
settings, e.g., settingshould give a response like
but it does not, at least from what I can tell. Maybe this is by design since the spec (https://www.rfc-editor.org/rfc/rfc7807) explicitly lists the properties lower/regular camel case, but it also doesn't seem to explicitly call out camelcase must be used. I think anyone who is using problem details should be able to use whatever casing their API uses already rather than being forced to either a) have inconsistent casing returned or b) use camel case.
Originally posted by @jchoca in #43261 (comment)
Repro:: https://github.com/jchoca/ProblemDetailsJsonSettings
The text was updated successfully, but these errors were encountered: