2

假设我有一个示例类:

public class SomeObject
{
    private FlagEnumerable _someFlagValue = FlagEnumerable.Flag1;

    public SomeObject()
    {
    }

    [DataMember(Name = "someFlagValue")]
    [Browsable(false)]
    public FlagEnumerable SomeFlagValue
    {
        get { return _someFlagValue; }
        set { _someFlagValue= value; }
    }
}

这就是我描述我的方式FlagEnumerable

[DataContract]
[Flags]
[JsonConverter(typeof(JsonEnumConverter))]
public enum FlagEnumerable
{
    [EnumMember]
    Flag1 = 1,

    [EnumMember]
    Flag2 = 2,

    [EnumMember]
    Flag3 = 4
}

此外,我有一个自定义 JSON 转换器,可以将我的枚举转换为字符串,将枚举标记为字符串数组,反之亦然。

此代码运行良好,并成功反序列化示例 JSON:

{
    someFlagValue: [
        "Flag1"
    ]
}

问题是如何将全局转换器应用于 JsonSerializer?当我从中删除[JsonConverter(typeof(JsonEnumConverter))]然后FlagEnumerable通过调用添加它时

MyJsonSerializer.Converters.Add(new JsonEnumConverter());

我收到此错误:

无法将当前 JSON 数组(例如 [1,2,3])反序列化为“FlagEnumerable”类型,因为该类型需要 JSON 原始值(例如字符串、数字、布尔值、null)才能正确反序列化。要修复此错误,请将 JSON 更改为 JSON 原始值(例如字符串、数字、布尔值、null)或将反序列化类型更改为数组或实现集合接口的类型(例如 ICollection、IList),例如可以是从 JSON 数组反序列化。JsonArrayAttribute 也可以添加到类型中以强制它从 JSON 数组反序列化。

任何帮助表示赞赏!抱歉,如果不清楚,请随时提出问题。

4

2 回答 2

2

我同样需要将可枚举的标志序列化为字符串数组。我认为自从您发布问题以来,情况发生了变化。我目前可以通过使用以下转换器来实现这一点:

[Flags]
enum FlagEnumerable
{
    Flag1 = 1,
    Flag2 = 2,
    Flag3 = 4
}

class FlagsEnumConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType.IsEnum && objectType.GetCustomAttributes(typeof(FlagsAttribute), false).Any();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var values = serializer.Deserialize<string[]>(reader);

        return values
            .Select(x => Enum.Parse(objectType, x))
            .Aggregate(0, (current, value) => current | (int) value);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var enumArr = Enum.GetValues(value.GetType())
            .Cast<int>()
            .Where(x => (x & (int) value) == x)
            .Select(x => Enum.ToObject(value.GetType(), x).ToString())
            .ToArray();

        serializer.Serialize(writer, enumArr);
    }
}

class Program
{
    static void Main(string[] args)
    {
        JsonConvert.DefaultSettings = () => new JsonSerializerSettings()
        {
            Converters = new List<JsonConverter>() {new FlagsEnumConverter()}
        };

        var targetObj = new { MyField = FlagEnumerable.Flag1 | FlagEnumerable.Flag3 };
        var str = JsonConvert.SerializeObject(targetObj);
        var deserializedObj = JsonConvert.DeserializeObject(str, targetObj.GetType());
    }
}
于 2014-09-29T17:02:45.117 回答
0

基于对这个问题的最高评价:JSON serialization of enum as string你需要的是StringEnumConverter.

使用它,这段代码:

SomeObject someObject = new SomeObject() { SomeFlagValue = FlagEnumerable.Flag3 };
string json = JsonConvert.SerializeObject(someObject,
    Newtonsoft.Json.Formatting.Indented,
    new Newtonsoft.Json.Converters.StringEnumConverter());

将产生这个 JSON:

{
    "SomeFlagValue": "Flag3"
}

请注意,在反序列化时似乎不需要传入 a StringEnumConverter——上面的 JSON 块可以很好地反序列化。

于 2013-02-06T07:23:09.727 回答