web-dev-qa-db-ja.com

オブジェクトタイプが指定されている場合に、JSON.NETにJArrayをList <object>に逆シリアル化するように指示するにはどうすればよいですか?

次のクラスを作成しましょう。

class Foo
{
    public object Any;
}

このクラスは、フィールドAnyのすべてを受け入れます。

私が電話するとき:

JsonConvert.DeserializeObject<Foo>("{any: 5}")

AnyにはSystem.Int64が含まれています。

しかし、私が電話すると:

JsonConvert.DeserializeObject<Foo>("{any: [5]}")

AnyにはNewtonsoft.Json.Linq.JArrayが含まれています。

この場合、AnyList<object>が含まれるようにJSON.NETを構成するにはどうすればよいですか?

説明:

何かあるかもしれません、私は呼ぶことができます:

JsonConvert.DeserializeObject<Foo>("{any: 'c'}")

または

JsonConvert.DeserializeObject<Foo>("{any: ['c', 5]}")

より明確にする:

どういうわけかJSON.NETに伝えたい(多分JsonSerializerSettingsを使用して):

objectに遭遇し、JSONに配列が含まれている場合は、それを(たとえば)List<object>に逆シリアル化します。

7
TN.

現在、私は次の解決策をあざけりました:

public class MyObjectConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(object);
    }

    public override object ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        switch (reader.TokenType)
        {
            case Newtonsoft.Json.JsonToken.StartArray:
                return JToken.Load(reader).ToObject<List<object>>(); 
            case Newtonsoft.Json.JsonToken.StartObject:
                return JToken.Load(reader).ToObject<Dictionary<string, object>>(); 
            default:
                if (reader.ValueType == null && reader.TokenType != Newtonsoft.Json.JsonToken.Null)
                    throw new NotImplementedException("MyObjectConverter");
                return reader.Value;
        }
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotSupportedException("MyObjectConverter");
    }
}

このソリューションの問題は、他のタイプも処理する必要があることです。 reader.TokenTypeがStartArrayでもStartObjectでもなく、reader.ValueTypeがnullの場合、失敗する可能性があります。うまくいけば、誰かがより良い解決策を提供するでしょう。

2
TN.

あなたの答えはおそらく ここ

きみの [5]は配列です。あなたがしなければならないのはそれをリストにキャストすることです。


ここで説明 のように、独自のコンバーターを作成することもできます。

2
Daniel Möller

JsonConverterでこれを行うことができると思います。以下のコンバーターは、anyフィールドがJArrayの場合、JArrayをオブジェクトのリストに変換し、それ以外の場合は、anyのデフォルトの動作にフォールバックします。あなたの説明に基づいて、これはまさにあなたが探しているものです。コードを改善できると思いますが、これで解決策への道が開かれるはずです。

public class ListJsonConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
        JsonSerializer serializer)
    {
        var theFoo = new Foo();

        dynamic dynamicObject = serializer.Deserialize(reader);

        if (dynamicObject.any.GetType() == typeof (JArray))
        {
            var items = new List<object>();

            foreach (var item in dynamicObject.any)
            {
                items.Add(item);
            }

            theFoo.Any = items;
        }
        else
        {
            theFoo.Any = dynamicObject.any.Value;
        }

        return theFoo;
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof (Foo);
    }

    public override bool CanRead
    {
        get { return true; }
    }

    public override bool CanWrite
    {
        get { return false; }
    }
}

使用法:

var bar = JsonConvert.DeserializeObject<Foo>("{any: ['c', 5]}", new ListJsonConverter());
0
Rob Davis