C# 将 json 字符反序列化为枚举

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18551452/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 12:34:38  来源:igfitidea点击:

Deserialize json character as enumeration

c#jsonjson.netenumerationjson-deserialization

提问by SelAromDotNet

I have an enumeration defined with C#, where I'm storing it's values as characters, like this:

我有一个用 C# 定义的枚举,我将它的值存储为字符,如下所示:

public enum CardType
{
    Artist = 'A',
    Contemporary = 'C',
    Historical = 'H',
    Musician = 'M',
    Sports = 'S',
    Writer = 'W'
}

I'm attempting to deserialize using JSON.NET, but the incoming JSON was written using the CHAR value (string) instead of the int value of the enumeration, like this:

我正在尝试使用 JSON.NET 进行反序列化,但传入的 JSON 是使用 CHAR 值(字符串)而不是枚举的 int 值编写的,如下所示:

[{"CardType","A"},{"CardType", "C"}]

Is it possible to define some kind of converter that will allow me to manually parse the char to the enum value?

是否可以定义某种转换器,允许我手动将字符解析为枚举值?

I tried creating a JsonConverter, but am not sure how to do it, while applying it only to this property and not the whole parsed object. here's what I tried:

我尝试创建一个 JsonConverter,但不知道该怎么做,同时仅将其应用于此属性而不是整个解析的对象。这是我尝试过的:

public class EnumerationConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
        {
            return null;
        }

        int value = serializer.Deserialize<int>(reader);
        return (CardType)value;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType.IsSubclassOf(typeof(string));
    }
}

The logic might be wrong and I can fix that but the problem is ReadJson() isn't being called at all.

逻辑可能是错误的,我可以解决这个问题,但问题是根本没有调用 ReadJson()。

CanConvert is, but it appears to be called for every property, not just the one property I defined it for:

CanConvert 是,但它似乎是为每个属性调用的,而不仅仅是我为其定义的一个属性:

public class Card
{
            private CardType type;
        [JsonConverter(typeof(EnumerationConverter))]
        public CardType Type
        {
            get { return type; }
            set { type = value; }
        }
}

I'm sure I've done this incorrectly but am having trouble finding documentation on how to do this for a single field...

我确定我做错了,但是我无法找到有关如何为单个字段执行此操作的文档...

What am I missing?

我错过了什么?

采纳答案by nemesv

You don't necessary need a custom JsonConverteryou can use the built in StringEnumConverterwith the combination of the EnumMemberAttribute(from the System.Runtime.Serializationassembly).

您不需要自定义JsonConverter您可以使用内置StringEnumConverterEnumMemberAttribute(来自System.Runtime.Serialization程序集)的组合。

Without the EnumMemberAttributeit uses the enum names so Artist, Contemporary, etc so you need to change the names with it to your A,C, etc value.

如果没有EnumMemberAttribute它,它使用枚举名称,因此艺术家、当代等,因此您需要将名称更改为您的 A、C 等值。

But it is not the nicest solution because you have to repeat your values two times, but it works:

但这不是最好的解决方案,因为您必须重复两次您的值,但它有效:

[JsonConverter(typeof(StringEnumConverter))]
public enum CardType
{
    [EnumMember(Value = "A")]
    Artist = 'A',
    [EnumMember(Value = "C")]
    Contemporary = 'C',
    [EnumMember(Value = "H")]
    Historical = 'H',
    [EnumMember(Value = "M")]
    Musician = 'M',
    [EnumMember(Value = "S")]
    Sports = 'S',
    [EnumMember(Value = "W")]
    Writer = 'W'
}

回答by Vladimir

This code works perfectly:

这段代码完美运行:

CardType[] array = { CardType.Artist, CardType.Contemporary };
string s = JsonConvert.SerializeObject(array);
var array2 = JsonConvert.DeserializeObject<CardType[]>(s);

Update:
What about out-of-box StringEnumConverter:

更新
开箱即用StringEnumConverter

[JsonConverter(typeof(StringEnumConverter))]
public CardType Type { get; set; }

回答by David-Paul Brown

You can just add SerializerSettings.Converters.Add(new StringEnumConverter());

您可以添加 SerializerSettings.Converters.Add(new StringEnumConverter());

to your BrowserJsonFormatter class

到您的 BrowserJsonFormatter 类

public class BrowserJsonFormatter : JsonMediaTypeFormatter
{
    public BrowserJsonFormatter()
    {
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
        SerializerSettings.Formatting = Formatting.Indented;
        SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
        SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
        SerializerSettings.Converters.Add(new EmptyToNullConverter());
        SerializerSettings.Converters.Add(new StringEnumConverter());
        //SerializerSettings.DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate;
    }

    public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
    {
        base.SetDefaultContentHeaders(type, headers, mediaType);
        headers.ContentType = new MediaTypeHeaderValue("application/json");
    }
}