我正在努力对象的反序列化...我在我的应用程序和web api中创建了相同的对象模型......它看起来像下面
public class Project
{
// some propeties of project object..
public SpecificationCollection Specs { get; set; }
public Project()
{
Specs = new SpecificationCollection();
}
}
[Serializable()]
public class SpecificationCollection : CollectionBase
{
public ProjectSpec this[int index]
{
get { return (ProjectSpec)List[index]; }
set { List[index] = value; }
}
//other implemented methods
}
public class ProjectSpec
{
//Properties
//Some other class object is also in this class but as of now i am not
//getting ProjectSpec
}
我尝试了以下内容:
{using newtonsoft refrence here}
Dim settings As New JsonSerializerSettings()
settings.TypeNameHandling = TypeNameHandling.All //asme in auto typenamehandling
Dim str As Object = Await response.Content.ReadAsStringAsync()
Dim deserializedList As Project = JsonConvert.DeserializeObject(Of Project)(str, settings)
这也是:
Await response.Content.ReadAsAsync(Of Project)()
我将Project对象转换为精细但不是集合。请建议如何评估这种情况。感谢
SAMPLE JSON
{"ProjectID":134,"ProjectName":"ABC","LPID":"","DNumber":0,"OrgnCode":"SPt","OrgnDesc":null,"SRatingCode":"AANSub","SRatingDesc":"AASub","ProjectConCode":"","ProjectCon":"desc","OrTCode":"Csity","OrTDesc":"Corsity","Projectsdf":"Miscld","ProjectType":"Miscellaneous","ProjectStatus":"","Street1":"","Street2":"","Street3":"","City":"Princeton","State":"NJ","StateName":"NY","PostalCode":"081","CountyCode":null,"CountyName":null,"CountryCode":"USA ","CountryName":"UNITED STATES","TCode":"AA03","TName":"A03","IsA":false,"IsF1":false,"IsF2":false,"IsBacked":false,"IsMeeting":false,"IsVerified":true,"HSpec":false,"NumSpecs":0,"BidDate":"1901-01-01T00:00:00","BidStartDate":"0001-01-01T00:00:00","BidEndDate":"0001-01-01T00:00:00","EnteredBy":"User","EnteredDate":"2014-02-26T14:39:00","LockedBy":null,"LockedDate":"0001-01-01T00:00:00","CreatedBy":"dfg","CreatedDate":"2014-02-26T14:39:00","ModifiedBy":"dfgl","ModifiedDate":"2014-05-07T15:03:00","DeletedDate":null,"SysDate":"2016-01-07T07:11:00","TotalRows":0,"MonthsBack":"0001-01-01T00:00:00","SkID":-2147483648,"ArchID":"dfgdfg","AuthoredBy":"0","DModifiedDate":"1901-01-01T00:00:00","DVersion":0,"Flag":0,"OClassCode":null,"ProjectOrClass":null,"StCode":"DEFAULT","StDesc":null,"Specs":[{"SpecId":51993,"ESpecID":"558","Origin":"OS","OrName":"Openings Studio","WriterID":null,"WriterName":null,"DistName":"","ArchitectName":null,"SpecDate":"0001-01-01T00:00:00","SpecEstBidDate":"0001-01-01T00:00:00","ContractorName":null,"ProductLines":null,"CreatedDate":"2014-03-10T11:34:00","CreatedBy":"dfgdfg","ModifiedDate":"2014-03-10T11:34:00","ModifiedBy":"dfgdfg","STProjectName":null,"OwnerType":null,"SRating":null,"StickRating":null,"ProjectValue":0.0},{"SpecId":52000,"ESpecID":"635","Origin":"dfgdfg","OrName":"dfgdfg","WriterID":null,"WriterName":null,"DistName":"","ArchitectName":null,"SpecDate":"0001-01-01T00:00:00","SpecEstBidDate":"0001-01-01T00:00:00","ContractorName":null,"ProductLines":null,"CreatedDate":"2014-03-10T14:08:00","CreatedBy":"SpecTrak","ModifiedDate":"2014-03-10T14:08:00","ModifiedBy":"dfgdfgdfg","STProjectName":null,"OwnerType":null,"SRating":null,"StickRating":null,"ProjectValue":0.0}]}
答案 0 :(得分:2)
问题是CollectionBase
是非通用的无类型集合,因此除非传入中存在$type
元数据属性,否则Json.NET无法知道如何反序列化其项目。 JSON - 他们显然不是。实际上,这个班级是considered to be obsolete。 Microsoft的准则When to Use Generic Collections声明:
通常建议使用泛型集合,因为您可以获得类型安全的直接好处,而无需从基本集合类型派生并实现特定于类型的成员。当集合元素是值类型时,泛型集合类型通常也比相应的非泛型集合类型(并且优于从非泛型集合类型派生的类型)执行得更好,因为使用泛型不需要对元素进行封装。
因此建议您继承System.Collections.ObjectModel.Collection<T>
:
public class SpecificationCollection : Collection<ProjectSpec>
{
}
话虽如此,如果您必须继续使用CollectionBase
,您可以让SpecificationCollection
实施ICollection<ProjectSpec>
在下面打字。如果你这样做,Json.NET将能够成功反序列化它:
[Serializable()]
public class SpecificationCollection : TypedCollectionBase<ProjectSpec>
{
}
[Serializable()]
public class TypedCollectionBase<TItem> : CollectionBase, IList<TItem>
{
#region IList<TItem> Members
public int IndexOf(TItem item)
{
return List.IndexOf(item);
}
public void Insert(int index, TItem item)
{
List.Insert(index, item);
}
public TItem this[int index]
{
get { return (TItem)List[index]; }
set { List[index] = value; }
}
#endregion
#region ICollection<TItem> Members
public void Add(TItem spec)
{
List.Add(spec);
}
public bool Contains(TItem item)
{
return List.Contains(item);
}
public void CopyTo(TItem[] array, int arrayIndex)
{
foreach (var item in this)
array[arrayIndex++] = item;
}
public bool IsReadOnly { get { return List.IsReadOnly; } }
public bool Remove(TItem item)
{
int index = IndexOf(item);
if (index >= 0)
RemoveAt(index);
return index >= 0;
}
#endregion
#region IEnumerable<TItem> Members
public new IEnumerator<TItem> GetEnumerator()
{
return List.Cast<TItem>().GetEnumerator();
}
#endregion
}
如果您无法以任何方式修改SpecificationCollection
的设计,则需要编写自己的JsonConverter
进行反序列化:
public class CollectionBaseConverter<TCollection, TItem> : JsonConverter where TCollection : CollectionBase
{
public override bool CanConvert(Type objectType)
{
return typeof(TCollection).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
TCollection collection = (TCollection)(existingValue ?? serializer.ContractResolver.ResolveContract(objectType).DefaultCreator());
var wrapper = new CollectionBaseWrapper<TCollection, TItem>(collection);
serializer.Populate(reader, wrapper);
return collection;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var collection = (TCollection)value;
serializer.Serialize(writer, collection.Cast<TItem>());
}
}
class CollectionBaseWrapper<TCollection, TItem> : ICollection<TItem> where TCollection : CollectionBase
{
readonly IList collection;
public CollectionBaseWrapper(TCollection collection)
{
if (collection == null)
throw new ArgumentNullException();
this.collection = collection;
}
public void Add(TItem item)
{
collection.Add(item);
}
public void Clear()
{
collection.Clear();
}
public bool Contains(TItem item)
{
return collection.Contains(item);
}
public void CopyTo(TItem[] array, int arrayIndex)
{
foreach (var item in this)
array[arrayIndex++] = item;
}
public int Count { get { return collection.Count; } }
public bool IsReadOnly { get { return collection.IsReadOnly; } }
public bool Remove(TItem item)
{
bool found = collection.Contains(item);
if (found)
collection.Remove(item);
return found;
}
public IEnumerator<TItem> GetEnumerator()
{
return collection.Cast<TItem>().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
然后在设置中使用它,如下所示:
var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto, Converters = new[] { new CollectionBaseConverter<SpecificationCollection, ProjectSpec>() } };
var deserializedList = JsonConvert.DeserializeObject<Project>(str, settings);