问题描述
我想从json创建不同对象类型的列表(具有相同的父对象).
I would like to create a list of different object types (with the same parent) from a 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键入
A quote have a collection of QuoteLines which can be A or B typed
我可以做这样的事情
Quote quote = new Quote{
QuoteLines = new List<QuoteLine>{
new A { Order = 1, PropertyA = "propA"},
new B { Order = 2, PropertyB = "propB"},
}
}
我想换一种方式我有一个这样的Json(从HttpClient.GetAsync()返回)
I want to do this in the other wayI have a Json like this (return from a HttpClient.GetAsync())
{"quoteLines":[
{"order":1,"propertyA":"propA"},
{"order":2,"propertyB":"propB"}
]}
当我将其反序列化为Quote时,我失去了children属性.我知道这是因为我有一个类型为QuoteLine的集合,所以不会反序列化children属性.但是我正在寻找一种保留所有信息的方法.
when I deserialize it into Quote, I loose the children properties.I understand it's because I have a collection typed QuoteLine so the children properties aren't deserialized. But I'm looking for a way to keep all informations.
我正在打的电话:
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;
}
感谢您的帮助.
推荐答案
我找到了一个更好的解决方案,它不会在json中公开名称空间和应用程序组装.
I found a better solution which doesn't expose namespace and app assembly in the json.
仅在客户端应用中.我添加了一个自定义的JsonConverter:
only in the client app.I added a custom 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();
}
}
}
我只需要向模型添加数据属性即可触发自定义转换器
And I only need to add a data attribute to my model to fire the custom converter
[JsonConverter(typeof(QuoteLineJsonConverter))]
public class QuoteLine
{
public int Order { get; set; }
}
对jquery ajax请求非常重视,您需要将数据作为Json发送以调用自定义JsonConverter.
Be carreful with jquery ajax request, you need to send the data as Json to call the custom JsonConverter.
$.ajax({
url: "myUrl",
type: "post",
cache: false,
data: JSON.stringify(data),
dataType: "json",
contentType: "application/json; charset=utf-8"
});
这篇关于如何从JSON创建具有不同对象类型的列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!