我想从json创建一个不同对象类型的列表(具有相同的父对象)。
我有一些型号
public class Quote
{
public virtual ICollection<QuoteLine> QuoteLines { get; set; }
}
public class QuoteLine
{
public int Order { get; set; }
}
public class A : QuoteLine
{
public string PropertyA { get; set; }
}
public class B : QuoteLine
{
public string PropertyB { get; set; }
}
引号包含引号行集合,可以是A或B类型
我可以做这样的事情
Quote quote = new Quote{
QuoteLines = new List<QuoteLine>{
new A { Order = 1, PropertyA = "propA"},
new B { Order = 2, PropertyB = "propB"},
}
}
我想换一种方式 我有一个这样的Json(从HttpClient.GetAsync()返回)
{"quoteLines":[
{"order":1,"propertyA":"propA"},
{"order":2,"propertyB":"propB"}
]}
当我将其反序列化为Quote时,我失去了children属性。 我知道这是因为我有一个类型为QuoteLine的集合,因此不会反序列化children属性。但是我正在寻找一种保留所有信息的方法。
我正在打的电话:
public async Task<Quote> GetById(int id)
{
Quote quote = null;
HttpResponseMessage response = await httpClient.GetAsync(new StringBuilder(controllerName).Append("/").Append(id).ToString());
if (response.IsSuccessStatusCode)
{
quote = await response.Content.ReadAsAsync<Quote>();
}
return quote;
}
感谢您的帮助。
答案 0 :(得分:2)
您需要为此目的在JsonSerializerSettings中使用TypeNameHandling。
JsonSerializerSettings settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All
};
var resultJson = JsonConvert.SerializeObject(quote,settings);
var resultobject = JsonConvert.DeserializeObject<Quote>(resultJson,settings);
验证输出
foreach(var item in resultobject.QuoteLines)
{
switch(item)
{
case A itemA :
Console.WriteLine($"Type A: {itemA.Order}, {itemA.PropertyA}");
break;
case B itemB :
Console.WriteLine($"Type A: {itemB.Order}, {itemB.PropertyB}");
break;
default:
Console.WriteLine("Error");
break;
}
}
输出
Type A: 1, propA
Type A: 2, propB
答案 1 :(得分:0)
如果不是必须使用这种特定的类层次结构,我建议仅保留一个类QuoteLine
,将所有字段放在其中,并摆脱类A和B。因此代码看起来像这样:
public class QuoteLine
{
public int Order { get; set; }
public string PropertyA { get; set; }
public string PropertyB { get; set; }
}
这样,json中不存在的字段将为null,您可以在使用前检查它们。
答案 2 :(得分:0)
我找到了一个更好的解决方案,它不会在json中公开名称空间和应用程序组装。
仅在客户端应用中。 我添加了一个自定义的JsonConverter:
public abstract class JsonCreationConverter<T> : JsonConverter
where T : class
{
public override bool CanWrite
{
get
{
return false;
}
}
protected abstract T Create(Type objectType, JObject jObject);
public override bool CanConvert(Type objectType)
{
return typeof(T).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader == null) throw new ArgumentNullException("reader");
if (serializer == null) throw new ArgumentNullException("serializer");
if (reader.TokenType == JsonToken.Null)
return null;
JObject jObject = JObject.Load(reader);
T target = Create(objectType, jObject);
serializer.Populate(jObject.CreateReader(), target);
return target;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
对于每个派生的实体:
public class QuoteLineJsonConverter : JsonCreationConverter<QuoteLine>
{
protected override QuoteLine Create(Type objectType, JObject jObject)
{
if (jObject == null) throw new ArgumentNullException("jObject");
string discriminator = jObject.GetValue("Discriminator", StringComparison.OrdinalIgnoreCase)?.Value<string>();
if (discriminator != null)
{
switch (discriminator)
{
case "A":
return new A();
case "B":
return new B();
default:
return new QuoteLine();
}
}
else
{
return new QuoteLine();
}
}
}
我只需要向模型添加数据属性即可触发自定义转换器
[JsonConverter(typeof(QuoteLineJsonConverter))]
public class QuoteLine
{
public int Order { get; set; }
}
对jquery ajax请求非常重视,您需要将数据作为Json发送以调用自定义JsonConverter。
$.ajax({
url: "myUrl",
type: "post",
cache: false,
data: JSON.stringify(data),
dataType: "json",
contentType: "application/json; charset=utf-8"
});