2016-03-23 13 views
0

Я борюсь с десериализации объекта ... Я создал ту же объектную модель как в моем приложении и веб-апи ... это выглядит как нижедесериализации объекта из ответа 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 
} 

I попробовал следующее:

{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)() 

Я получаю объект проекта преобразуется п но не коллекцию. Пожалуйста, совет, как оценить эту ситуацию. Благодаря

ОБРАЗЦА 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

Web API делает десериализации объектов. Вы можете проверить эту ссылку, чтобы проверить, совместим ли ваш объект Project с ожидаемым JSON. http://jsonutils.com/ –

+1

Положите свою строку json –

+0

см. обновление редактирования ..... я передал то же самое в ссылке выше Сома ... его создание IList .... я попробовал это в своем приложении и работал отлично ... могу я получить его в объект коллекции? поскольку он уже реализован во многих местах, изменение –

ответ

2

Проблема заключается в том, что CollectionBase не является универсальным, нетипизированным коллекция, и, таким образом, Json.NET не имеет возможности узнать, как десериализации его элементы если $type свойства метаданных не присутствуют в входящем JSON, который, по-видимому, нет. Фактически, этот класс равен considered to be obsolete. руководство When to Use Generic Collections состояние компании Microsoft:

Использование обобщенных коллекций, как правило, рекомендуется, потому что вы получаете немедленную выгоду безопасности типа без необходимости получения от типа базового сбора и реализации членов типа конкретного. Типичные типы коллекций также обычно лучше, чем соответствующие типы неорганизованных коллекций (и лучше, чем типы, которые производятся из типов неродственных базовых коллекций), когда элементы коллекции являются типами значений, потому что с помощью дженериков нет необходимости вставлять элементы.

Поэтому рекомендуются вместо того, чтобы наследовать от 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); 
Смежные вопросы