提问者:小点点

使用 JSON.Net 的 C# JSON 字符串反序列化


我会有我的 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])或更改反序列化类型,使其是可以从 JSON 对象反序列化的普通 .NET 类型(例如,不是整数等基元类型,也不是数组或列表等集合类型)。还可以将 JsonObjectAttribute 添加到类型中,以强制它从 JSON 对象反序列化。

路径“名称字符串”,第 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);

打印:

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、ClassType 的访问权限或添加构造函数:

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

匿名用户

名称不是一个数组,它是一个对象:

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/ 创建的类