2015-09-28 6 views
2

Я бы мой JSON строку, как показано ниже, которая должна быть десериализован к ниже классаC# JSON Строка десериализации с помощью Json.NET

{ 
    "Id":"1", 
    "Names":{ 
     "string":"Surya" 
    }, 
    "ClassTypes":{ 
     "Types":[ 
      { 
       "TypeId":"1", 
       "TypeName":"First Name" 
      }, 
      { 
       "TypeId":"2", 
       "TypeName":"Last Name" 
      } 
     ] 
    }, 
    "Status":"1", 
    "DOB":"23/12/2014" 
} 

Определение класса

public class MyClass 
{ 
    public int Id { get; set; } 
    public IList<string> Names { get; protected set; } 
    public IList<Types> ClassTypes { get; protected set; } 
    public StatusType Status { get; set; } 
    public DateTime DOB { get; set; } 

    public MyClass() 
    { 
     Names = new List<string>(); 
     ClassTypes = new List<Types>(); 
     Status = StatusType.Active; 
    } 
} 
public class Types 
{ 
    public int TypeId { get; set; } 
    public string TypeName { get; set; } 
} 

public enum StatusType 
{ 
    Active = 0, 
    InActive = 1 
} 

Я использовал следующий код для десериализации, но получаю ошибки

var serializerSettings = new JsonSerializerSettings(); 
serializerSettings.ContractResolver = new IncludeNonPublicMembersContractResolver(); 
JsonConvert.DeserializeObject<MyClass>(jsonString, serializerSettings); 

public class IncludeNonPublicMembersContractResolver : DefaultContractResolver 
{ 
    public IncludeNonPublicMembersContractResolver() 
    { 
     DefaultMembersSearchFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; 
    } 
    protected override List<MemberInfo> GetSerializableMembers(Type objectType) 
    { 
     var members = base.GetSerializableMembers(objectType); 
     return members.Where(m => !m.Name.EndsWith("k__BackingField")).ToList(); 
    } 

} 

Сведения об ошибке

Невозможно десериализовать текущий объект JSON (например, {"name": "value"}) в тип 'System.Collections.Generic.IList`1 [System.String]', потому что для типа требуется массив JSON (например, [1,2,3]) для десериализации правильно.

Чтобы исправить эту ошибку, либо изменить JSON в массив JSON (например [1,2,3]) или изменить десериализованное типа, так что это нормально .NET типа (например, не примитивный тип, как целое , а не тип коллекции как массив или список), которые можно десериализовать из объекта JSON. JsonObjectAttribute также можно добавить к типу, чтобы заставить его десериализовать объект JSON.

Путь «Names.string», строка 1, позиция 28.

Примечание - Я не могу изменить с помощью JSON строки и решения более общего имеет это требовалось бы для других классов, а также: (

ответ

2

Один из способов заключается в использовании JsonConverter:

public class MyClass 
    { 
     public int Id { get; set; } 
     [JsonProperty("Names"), JsonConverter(typeof(NamesConverter))] 
     public IList<string> Names { get; protected set; } 
     [JsonProperty("ClassTypes"), JsonConverter(typeof(TypesConverter))] 
     public IList<Types> ClassTypes { get; protected set; } 
     public StatusType Status { get; set; } 
     [JsonProperty("DOB"), JsonConverter(typeof(DateTimeConverter))] 
     public DateTime DOB { get; set; } 

     public MyClass() 
     { 
      Names = new List<string>(); 
      ClassTypes = new List<Types>(); 
      Status = StatusType.Active; 
     } 

     public override string ToString() 
     { 
      return 
       string.Format("ID: {0}\nNames:\n{1}\nClassTypes:\n{2}Status: {3}\nDOB: {4}", 
       Id, string.Join("\n", Names), string.Join("\n", ClassTypes), Status, DOB); 
     } 
    } 
    public class Types 
    { 
     public int TypeId { get; set; } 
     public string TypeName { get; set; } 

     public override string ToString() 
     { 
      return string.Format("\tTypeId: {0}\n\tTypeName: {1}\n", TypeId, TypeName); 
     } 
    } 

    public enum StatusType 
    { 
     Active = 0, 
     InActive = 1 
    } 

    class NamesConverter : JsonConverter 
    { 
     public override bool CanConvert(Type objectType) 
     { 
      return typeof(Dictionary<string, string>).IsAssignableFrom(objectType); 
     } 

     public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
     { 
      return serializer.Deserialize<Dictionary<string, string>>(reader).Values.ToList(); 
     } 

     public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
     { 
      throw new NotImplementedException(); 
     } 

    } 
    class TypesConverter : JsonConverter 
    { 
     public override bool CanConvert(Type objectType) 
     { 
      return typeof(Dictionary<string,List<Types>>).IsAssignableFrom(objectType); 
     } 

     public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
     { 
      return serializer.Deserialize<Dictionary<string,List<Types>>>(reader) 
       .Values.First().ToList(); 
     } 

     public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
     { 
      throw new NotImplementedException(); 
     } 

    } 
    class DateTimeConverter : JsonConverter 
    { 
     public override bool CanConvert(Type objectType) 
     { 
      return typeof(string).IsAssignableFrom(objectType); 
     } 

     public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
     { 
      return DateTime.ParseExact(serializer.Deserialize<string>(reader), @"dd\/MM\/yyyy", null); 
     } 

     public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
     { 
      throw new NotImplementedException(); 
     } 

    } 

...

var jsonobj = JsonConvert.DeserializeObject<MyClass>(json); 
    Console.WriteLine(jsonobj); 

Print:

Names: 
Surya 
ClassTypes: 
    TypeId: 1 
    TypeName: First Name 

    TypeId: 2 
    TypeName: Last Name 
Status: InActive 
DOB: 12/23/2014 12:00:00 AM 

https://dotnetfiddle.net/EfQuET

Двухсторонний - разобрать JSON, но тогда вы необходимо изменить доступ к свойствам Имена, ClassTypes или добавить конструктор:

var jObject = JObject.Parse(json); 
var names = new List<string> 
{ 
    jObject["Names"].Value<string>("string") 
}; 
var types = jObject["ClassTypes"]["Types"] 
    .Select(x => new Types 
    { 
     TypeId = x.Value<int>("TypeId"), 
     TypeName = x.Value<string>("TypeName") 
    }) 
     .ToList(); 
var data = new MyClass(names,types) 
{ 
    Id = jObject.Value<int>("Id"), 
    Status = (StatusType)Enum.Parse(typeof(StatusType),jObject.Value<string>("Status")), 
    DOB = DateTime.ParseExact(jObject.Value<string>("DOB"), @"dd\/MM\/yyyy", null) 
}; 

Console.WriteLine(data); 

https://dotnetfiddle.net/HcPxT9

2

Names не является массивом, это объект:

public class Names 
{ 
    public string @string { get; set; } 
} 

public class Type 
{ 
    public string TypeId { get; set; } 
    public string TypeName { get; set; } 
} 

public class ClassTypes 
{ 
    public List<Type> Types { get; set; } 
} 

public class MyClass 
{ 
    public int Id { get; set; } 
    public Names Names { get; set; } 
    public ClassTypes ClassTypes { get; set; } 
    public string Status { get; set; } 
    public string DOB { get; set; } 
} 
... 

var result = JsonConvert.DeserializeObject<MyClass>(jsonString); 

Классы созданы http://json2csharp.com/

+1

Upvote для json2csharp :) – niksofteng

+0

Я искал код десериализации строки JSON в объекте класса – suryakiran

+0

@suryakiran и почему мой ответ вам не поможет? – Backs

Смежные вопросы