Newtonsoft.Json
Newtonsoft.Json copied to clipboard
StringEnumConverter does not contain decodeURI
Env: Js code call http api
Source/destination types
[Description("启用/禁用")]
public enum EnableDisable
{
[EnumMember(Value = "禁用")]
Disable = 0,
[EnumMember(Value = "启用")]
Enable = 1,
}
public class DestType { public EnableDisable StatusEnum { get; set; } }
Source/destination JSON
{"StatusEnum":"%E7%A6%81%E7%94%A8"}
Expected behavior
Want StringEnumConverter
to allow decodeuri before judging enumeration.
I think we can use these methods:
- Rewrite the
StringEnumConverter
class and decode it before calling the parent class readjson.This allows users to inherit the code themselves -
StringEnumConverter
Construction method increase judgment. - Global control, adding decoding configuration
Actual behavior
not support convert string To enum
Fortunately, you can already achieve the desired functionality without requiring changes to the Newtonsoft.Json library.
Unfortunately, it relies on Newtonsoft.Json functionality that is really. really, really poorly and insufficiently documented, in particular how it the respective functionality works in conjunction with StringEnumConverter :sob:
The key to make the functionality you want working is in utilizing StringEnumConverter's NamingStrategy property (which can also be set through one of StringEnumConverter's constructors).
NamingStrategy is used by StringEnumConverter to convert enum values to a particular json representation (think of choosing between camel-case, kebap-case, snake-case, etc...).
Now, importantly, NamingStrategy is a (abstract) class that can be derived from to implement a custom naming strategy, basically exactly what you want (in your case, you want a url-encode naming scheme for your enum values).
In its most basic form, a custom NamingStrategy class that implements the url-encode naming scheme you want could look like this:
public class UrlEncodeNamingStrategy : Newtonsoft.Json.Serialization.NamingStrategy
{
protected override string ResolvePropertyName(string name)
=> HttpUtility.UrlEncode(name);
public UrlEncodeNamingStrategy()
{
OverrideSpecifiedNames = true;
}
}
Note that the OverrideSpecifiedNames property of the custom NamingStrategy has to be set to true
, otherwise the StringEnumConverter won't utilize the naming strategy.
A full example using the UrlEncodeNamingStrategy from above (dotnetfiddle: https://dotnetfiddle.net/oFvyy0):
var settings = new JsonSerializerSettings
{
Converters = new JsonConverter[] { new StringEnumConverter(new UrlEncodeNamingStrategy()) }
};
var json1 = @"{""StatusEnum"":""%E7%A6%81%E7%94%A8""}";
var result1 = JsonConvert.DeserializeObject<DestType>(json1, settings);
Console.WriteLine($"result1.StatusEnum = {result1.StatusEnum}");
var json2 = @"{""StatusEnum"":""%e5%90%af%e7%94%a8""}";
var result2 = JsonConvert.DeserializeObject<DestType>(json2, settings);
Console.WriteLine($"result2.StatusEnum = {result2.StatusEnum}");
(I deleted my previous second comment as it turns out that you don't need to do what i suggested there. If the json data for some enum value is just plain text instead of being url-encoded, Newtonsoft.Json deserialization routine still handles this just fine also when a StringEnumConverter with UrlEncodeNamingStrategy is being used. My apologies for talking rubbish earlier :-) )