C#Json.NET将标志枚举呈现为字符串数组

时间:2017-03-31 14:27:41

标签: c# json enums json.net

在.NET应用程序中,我有一组存储为ContT的值。我想将这些序列化为json,但是我没有将结果作为整数,而是希望为活动的标志获取一个字符串数组。

所以,如果我有以下代码

[Flags] enum

我希望[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 }); } 方法返回:

Serialize()

而不是:

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

5 个答案:

答案 0 :(得分:12)

您必须实施自己的转换器。这是一个例子(一种特别肮脏和黑客的方式,但它可以作为一个很好的演示):

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;
    }
}

现在装饰你的枚举:

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

您的示例序列化代码现在将输出:

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

答案 1 :(得分:5)

装饰你的enum

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

输出:

  

{“Flags”:“Val1,Val4”}

我意识到JSON不是你问题中的数组,不确定这是否是必需的,因为这也是有效的JSON。

答案 2 :(得分:1)

此答案与OP请求的序列化稍有不同,但可能仍然有用。它基于@davidg的解决方案,但是序列化的JSON看起来像这样(对于1 + 4 = 5):

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

标志枚举的修饰与Davids答案中的修饰相同:

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

但是这里有一个不同的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;
    }
}

答案 3 :(得分:1)

我使用了@DavidG的答案,但需要ReadJson的实现。这是我整理的:

        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;
        }

答案 4 :(得分:0)

 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;

        }

使用类似

ConvertEnumsToJson<byte>(typeof(AnyEnum))