给出这个JSON:
[
{
"$id": "1",
"$type": "MyAssembly.ClassA, MyAssembly",
"Email": "me@here.com",
},
{
"$id": "2",
"$type": "MyAssembly.ClassB, MyAssembly",
"Email": "me@here.com",
}
]
和这些类:
public abstract class BaseClass
{
public string Email;
}
public class ClassA : BaseClass
{
}
public class ClassB : BaseClass
{
}
如何将JSON反序列化为:
IEnumerable<BaseClass> deserialized;
我无法使用JsonConvert.Deserialize<IEnumerable<BaseClass>>()
,因为它抱怨BaseClass
是抽象的。
答案 0 :(得分:77)
你需要:
JsonSerializerSettings settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
};
string strJson = JsonConvert.SerializeObject(instance, settings);
所以JSON看起来像这样:
{
"$type": "System.Collections.Generic.List`1[[MyAssembly.BaseClass, MyAssembly]], mscorlib",
"$values": [
{
"$id": "1",
"$type": "MyAssembly.ClassA, MyAssembly",
"Email": "me@here.com",
},
{
"$id": "2",
"$type": "MyAssembly.ClassB, MyAssembly",
"Email": "me@here.com",
}
]
}
然后你可以反序列化它:
BaseClass obj = JsonConvert.DeserializeObject<BaseClass>(strJson, settings)
答案 1 :(得分:12)
这是一种在不在json中填充$ type的方法。
Json转换器:
public class FooConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(BaseFoo));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
if (jo["FooBarBuzz"].Value<string>() == "A")
return jo.ToObject<AFoo>(serializer);
if (jo["FooBarBuzz"].Value<string>() == "B")
return jo.ToObject<BFoo>(serializer);
return null;
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
使用它:
var test = JsonConvert.DeserializeObject<List<BaseFoo>>(result, new JsonSerializerSettings()
{
Converters = { new FooConverter() }
});
取自here
答案 2 :(得分:6)
在反序列化时使用以下JsonSerializerSettings构造:
new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.Objects
})
答案 3 :(得分:0)
您还可以将枚举包装在一个类中:
class Wrapper
{
IEnumerable<BaseClass> classes;
}
然后序列化并反序列化。
答案 4 :(得分:0)
由于我只需要一个用于特定基类的一侧序列化程序(以使API返回派生类的属性),我想出了当前的解决方案
public class CustomConverter : JsonConverter<BaseClass>
{
private readonly JsonSerializerOptions _serializerOptions;
public CustomConverter()
{
_serializerOptions = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
IgnoreNullValues = true,
};
}
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(BaseClass));
}
public override BaseClass Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
public override void Write(Utf8JsonWriter writer, BaseClass value, JsonSerializerOptions options)
{
writer.WriteStringValue(JsonSerializer.SerializeToUtf8Bytes(value, value.GetType(), _serializerOptions));
}
}