简体   繁体   English

C# Json.NET Render 将枚举标记为字符串数组

[英]C# Json.NET Render Flags Enum as String Array

In a .NET Application, I have a set of values that are stored as a [Flags] enum .在 .NET 应用程序中,我有一组存储为[Flags] enum I want to serialize these to json, but instead of having the result be an integer, I'd like to get an array of string for the flags that are active.我想将这些序列化为 json,但不是让结果是一个整数,我想为活动的标志获取一个字符串数组。

So if I have the following code所以如果我有以下代码

[Flags]
public enum F
{
    Val1 = 1,
    Val2 = 2,
    Val4 = 4,
    Val8 = 8

}

public class C
{        
    public F Flags { get; set; }
}

string Serialize() {
    return JsonConvert.SerializeObject(new C { Flags = F.Val1 | F.Val4 });
}

I want the Serialize() method to return:我希望Serialize()方法返回:

"{ Flags: [ "Val1", "Val4" ] }"

Instead of:代替:

"{ Flags: 5 }"

You have to implement your own converter.您必须实现自己的转换器。 Here's an example (a particularly dirty and hacky way of doing it, but it serves as a good demo):这是一个例子(一种特别肮脏和骇人听闻的做法,但它作为一个很好的演示):

public class FlagConverter : JsonConverter
{
    public override object ReadJson(JsonReader reader,  Type objectType, Object existingValue, JsonSerializer serializer)
    {
        //If you need to deserialize, fill in the code here
        return null;
    }

    public override void WriteJson(JsonWriter writer, Object value, JsonSerializer serializer)
    {
        var flags = value.ToString()
            .Split(new[] { ", " }, StringSplitOptions.RemoveEmptyEntries)
            .Select(f => $"\"{f}\"");

        writer.WriteRawValue($"[{string.Join(", ", flags)}]");
    }

    public override bool CanConvert(Type objectType)
    {
        return true;
    }
}

Now decorate your enum like this:现在像这样装饰你的枚举:

[Flags]
[JsonConverter(typeof(FlagConverter))]
public enum F
{
    Val1 = 1,
    Val2 = 2,
    Val4 = 4,
    Val8 = 8
}

And your example serialisation code will now output this:您的示例序列化代码现在将输出:

{"Flags":["Val1", "Val4"]}

Decorate your enum装饰你的enum

[Flags]
[JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
public enum F
{
    Val1 = 1,
    Val2 = 2,
    Val4 = 4,
    Val8 = 8
}

Output:输出:

{"Flags":"Val1, Val4"} {"Flags":"Val1, Val4"}

I realise the JSON is not an array as in your question, wasn't sure if this was required since this is also valid JSON.我意识到 JSON 不是您问题中的数组,不确定是否需要这样做,因为这也是有效的 JSON。

I used @DavidG's answer above, but needed an implementation for ReadJson.我在上面使用了@DavidG 的答案,但需要一个 ReadJson 的实现。 Here's what I put together:这是我整理的:

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    int outVal = 0;
    if (reader.TokenType == JsonToken.StartArray)
    {
        reader.Read();
        while (reader.TokenType != JsonToken.EndArray)
        {
            outVal += (int)Enum.Parse(objectType, reader.Value.ToString());
            reader.Read();
        }
    }
    return outVal;
}

This answer slightly differs from the serialization requested by OP but might be useful nonetheless.这个答案与 OP 请求的序列化略有不同,但可能有用。 It's based on the solution by @davidg but the serialized JSON looks like this (for 1+4=5):它基于@davidg 的解决方案,但序列化的 JSON 如下所示(对于 1+4=5):

{
    "Val1": true,
    "Val2": false,
    "Val4": true,
    "Val8": false  
}

The decoration of the flags enum is the same as in Davids answer:标志枚举的装饰与 Davids 的回答相同:

[Flags]
[JsonConverter(typeof(FlagConverter))]
public enum F
{
    Val1 = 1,
    Val2 = 2,
    Val4 = 4,
    Val8 = 8
}

But here's a different WriteJson method and a minimal working example for a ReadJson method.但这里有一个不同的WriteJson方法和一个最小的工作例如ReadJson方法。

public class FlagConverter : JsonConverter
{
    public override object ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)
    {
        JToken token = JToken.Load(reader);
        JObject jobject = JObject.FromObject(token);
        F result = 0;
        foreach (F f in Enum.GetValues(typeof(F)))
        {
            if (jobject[f.ToString()] != null && (bool)jobject[f.ToString()])
            {
                result |= f; // key is present and value is true ==> set flag
            }
        }
        return result;
    }

    public override void WriteJson(JsonWriter writer, Object value, JsonSerializer serializer)
    {
        JObject result = new JObject();
        F f = (F)value;
        foreach (F f in Enum.GetValues(typeof(F)))
        {
            result[f.ToString()] = status.HasFlag(f);
        }
        writer.WriteRawValue(JsonConvert.SerializeObject(result));
    }

    public override bool CanConvert(Type objectType)
    {
        return true;
    }
}
 public static string ConvertEnumsToJson<T>(Type e)
        {

            var ret = "{";
            var index = 0;
            foreach (var val in Enum.GetValues(e))
            {
                if (index > 0)
                {
                    ret += ",";
                }
                var name = Enum.GetName(e, val);
                ret += name + ":" + ((T)val) ;
                index++;
            }
            ret += "}";
            return ret;

        }

Use Like使用喜欢

ConvertEnumsToJson<byte>(typeof(AnyEnum))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM