次のクラスを作成しましょう。
class Foo
{
public object Any;
}
このクラスは、フィールドAny
のすべてを受け入れます。
私が電話するとき:
JsonConvert.DeserializeObject<Foo>("{any: 5}")
Any
にはSystem.Int64
が含まれています。
しかし、私が電話すると:
JsonConvert.DeserializeObject<Foo>("{any: [5]}")
Any
にはNewtonsoft.Json.Linq.JArray
が含まれています。
この場合、Any
にList<object>
が含まれるようにJSON.NETを構成するにはどうすればよいですか?
説明:
何かあるかもしれません、私は呼ぶことができます:
JsonConvert.DeserializeObject<Foo>("{any: 'c'}")
または
JsonConvert.DeserializeObject<Foo>("{any: ['c', 5]}")
より明確にする:
どういうわけかJSON.NETに伝えたい(多分JsonSerializerSettingsを使用して):
object
に遭遇し、JSONに配列が含まれている場合は、それを(たとえば)List<object>
に逆シリアル化します。
現在、私は次の解決策をあざけりました:
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の場合、失敗する可能性があります。うまくいけば、誰かがより良い解決策を提供するでしょう。
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());