【问题标题】:C# JSON String Deserialization using JSON.Net使用 JSON.Net 的 C# JSON 字符串反序列化
【发布时间】:2015-09-28 05:32:26
【问题描述】:

我的 JSON 字符串如下所示,需要反序列化为下面的类

{
    "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 字符串和更通用的解决方案进行更改,其他类也需要这样做:(

【问题讨论】:

    标签: c# json serialization json.net


    【解决方案1】:

    一种方法是使用 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);
    

    打印:

    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,但是您需要更改属性 Names、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/创建的类

      【讨论】:

      • 我正在寻找将 JSON 字符串反序列化为类对象的代码
      • @suryakiran 为什么我的回答对你没有帮助?
      • 因为我的课程也不能修改
      • 使用中间类(如答案中所述)并将数据手动复制到所需类的平面数组中。您遇到了类和 JSON 结构不匹配的问题。您还可以修改 JSON 文本。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多