Skip to content
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

JsonStringEnumConverter ignores 'allowIntegerValues' when deserializing quoted numeric values #58247

Closed
DenisAloner opened this issue Aug 27, 2021 · 11 comments · Fixed by #79432
Labels
area-System.Text.Json breaking-change Issue or PR that represents a breaking API or functional change over a prerelease. bug help wanted [up-for-grabs] Good issue for external contributors needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet Priority:3 Work that is nice to have
Milestone

Comments

@DenisAloner
Copy link

.NET 5
JsonStringEnumConverter ignores JsonNumberHandling.Strict on deserialization.
Example: https://dotnetfiddle.net/IsP6Dn

@dotnet-issue-labeler dotnet-issue-labeler bot added area-System.Text.Json untriaged New issue has not been triaged by the area owner labels Aug 27, 2021
@ghost
Copy link

ghost commented Aug 27, 2021

Tagging subscribers to this area: @eiriktsarpalis, @layomia
See info in area-owners.md if you want to be subscribed.

Issue Details

.NET 5
JsonStringEnumConverter ignores JsonNumberHandling.Strict on deserialization.
Example: https://dotnetfiddle.net/IsP6Dn

Author: DenisAloner
Assignees: -
Labels:

area-System.Text.Json, untriaged

Milestone: -

@eiriktsarpalis
Copy link
Member

This by design, number handling only applies to numeric types and not enums (this includes the default enum converter and not just JsonStringEnumConverter).

Out of curiosity, what would be your expected behavior in that snippet? Assuming strict number handling was respected, it would directly contradict what JsonStringEnumConverter is supposed to do (that is, express enums as strings as opposed to their underlying numeric values).

@DenisAloner
Copy link
Author

DenisAloner commented Aug 27, 2021

Thank you for your quick response!
I expected that these options will result in the following:
{"Value" : 0} - not valid
{"Value" : "0"} - not valid
{"Value" : "On"} - valid
{"Value" : "Off"} - valid
But the example shows that these options give the following:
{"Value" : 0} - not valid
{"Value" : "0"} - valid
{"Value" : "On"} - valid
{"Value" : "Off"} - valid

@eiriktsarpalis
Copy link
Member

I see; while the issue is unrelated to JsonNumberHandling, the allowIntegerValues parameter is not honored when the undefined enum is encoded as a string. Minimal reproduction:

using System;
using System.Text.Json;
using System.Text.Json.Serialization;

public class Program
{
    public static void Main()
    {
        var options = new JsonSerializerOptions { Converters = { new JsonStringEnumConverter(allowIntegerValues: false) } };
        Console.WriteLine(JsonSerializer.Deserialize<MyEnum>("\"42\"", options)); // does not fail
        Console.WriteLine(JsonSerializer.Deserialize<MyEnum>("42", options)); // fails as expected
    }
    
    public enum MyEnum
    {
        Value = 1
    }
}

I would say we should fix this.

@eiriktsarpalis eiriktsarpalis changed the title JsonStringEnumConverter ignores JsonNumberHandling.Strict on deserialization JsonStringEnumConverter ignores 'allowIntegerValues' when deserializing quoted numeric values Aug 27, 2021
@eiriktsarpalis eiriktsarpalis removed the untriaged New issue has not been triaged by the area owner label Aug 27, 2021
@eiriktsarpalis eiriktsarpalis added this to the 7.0.0 milestone Aug 27, 2021
@eiriktsarpalis eiriktsarpalis added bug Priority:3 Work that is nice to have labels Aug 27, 2021
@wsugarman
Copy link
Contributor

Back to the original question, I think allowing integers encoded as strings violates the spirit of this parameter. For example, developers may use JsonStringEnumConverter in their ASP.NET Core projects such their users can specify enumeration names in the request body. This is great because the names are much more description than using numbers. However, I think developers may also assume that they've also decoupled their enum integral values from their web APIs, but this isn't the case. A user could still pass the integral values as strings and successfully bind to the model.

I understand that accepting both the string and integral representations has precedence with use cases like Enum.TryParse, but personally I would like the option to impose more strictness on my JSON parsing. It would be a welcomed addition if this was provided out-of-the-box.

@eiriktsarpalis
Copy link
Member

Moving to Future, as we won't have time to work on this in the .NET 7 timeframe.

@layomia
Copy link
Contributor

layomia commented Dec 2, 2022

Up for grabs. I believe the fix here would be to enforce that only named constants are permitted when reading enum values as strings and allowIntegerValues is false.

The relevant code would need to be added to this method.

@layomia layomia added the help wanted [up-for-grabs] Good issue for external contributors label Dec 2, 2022
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Dec 9, 2022
@davisnw
Copy link

davisnw commented Dec 20, 2022

As of 2022-12-19, the documentation at https://learn.microsoft.com/en-us/dotnet/api/system.text.json.serialization.jsonstringenumconverter.-ctor?view=net-7.0#system-text-json-serialization-jsonstringenumconverter-ctor(system-text-json-jsonnamingpolicy-system-boolean) states:

allowIntegerValues Boolean

true to allow undefined enum values; otherwise, false. When true, if an enum value isn't defined, it will output as a number rather than a string.

This clearly implies that you should never receive undefined enum values when parsing with allowIntegerValues: false.

I could see this discrepancy leading to security vulnerabilities in some api usage contexts.

(Note: for some reason the links to file feedback on the documentation via github is not available for that page)

@ckarcz
Copy link

ckarcz commented Dec 22, 2022

workaround for now https://stackoverflow.com/a/74890774/929401

@ghost ghost added in-pr There is an active PR which will close this issue when it is merged and removed in-pr There is an active PR which will close this issue when it is merged labels Mar 6, 2023
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Oct 6, 2023
@eiriktsarpalis eiriktsarpalis added the breaking-change Issue or PR that represents a breaking API or functional change over a prerelease. label Oct 6, 2023
@eiriktsarpalis eiriktsarpalis modified the milestones: Future, 9.0.0 Oct 6, 2023
@ghost ghost added the needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet label Oct 6, 2023
@ghost
Copy link

ghost commented Oct 6, 2023

Added needs-breaking-change-doc-created label because this issue has the breaking-change label.

  1. Create and link to this issue a matching issue in the dotnet/docs repo using the breaking change documentation template, then remove this needs-breaking-change-doc-created label.

Tagging @dotnet/compat for awareness of the breaking change.

@eiriktsarpalis
Copy link
Member

The fix is technically a breaking change since disabling integers no longer accepts strings containing integers. The workaround is trivial (just enable integers) but we should still document it.

@ghost ghost locked as resolved and limited conversation to collaborators Nov 5, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Text.Json breaking-change Issue or PR that represents a breaking API or functional change over a prerelease. bug help wanted [up-for-grabs] Good issue for external contributors needs-breaking-change-doc-created Breaking changes need an issue opened with https://github.com/dotnet/docs/issues/new?template=dotnet Priority:3 Work that is nice to have
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants