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 など) に変更するか、逆シリアル化された型を配列または List のようなコレクション インターフェイス (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 what you need is the 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 に答える