我正在尝试反序列化以下JSON文件:http://komunikaty.tvp.pl/komunikatyxml/malopolskie/wszystkie/0?_format=json
我的c#代码:
MemoryStream stream1 = new MemoryStream();
StreamWriter writer = new StreamWriter(stream1);
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(ApiRegionalne));
writer.Write(json);
writer.Flush();
stream1.Position = 0;
dane = (ApiRegionalne)ser.ReadObject(stream1);
我的班级:
[DataContract]
public class newses
{
public int id;
public string title;
public bool shortcut;
public string content;
public bool rso_alarm;
public string rso_icon;
public string longitude;
public string latitude;
public int water_level_value;
public int water_level_warning_status_value;
public int water_level_alarm_status_value;
public int water_level_trend;
public string river_name;
public string location_name;
public string type;
}
[DataContract]
public class ApiRegionalne
{
[DataMember(Name = "newses")]
public newses[] newses;
}
JSON反序列化器不会抛出任何异常,但我的数据仍为空。
我做错了什么?
答案 0 :(得分:2)
您需要将类newses
的所有公共字段标记为合同的一部分:
[DataContract]
public class newses
{
[DataMember(Name = "id")] //This is what you need to add
public int id;
//Do the same for all other fields
}
答案 1 :(得分:2)
您的基本问题是数据合约序列化程序(DataContractSerializer
和DataContractJsonSerializer
)选择加入。如果您使用[DataContract]
标记类型,则还必须使用[DataMember]
标记要序列化的成员,如Using Data Contracts中所述:
您还可以使用DataContractAttribute和DataMemberAttribute属性明确创建数据合同。这通常通过将DataContractAttribute属性应用于该类型来完成。此属性可以应用于类,结构和枚举。然后,必须将DataMemberAttribute属性应用于数据协定类型的每个成员,以指示它是数据成员,即应该序列化。
您尚未将[DataMember]
应用于newses
类型的任何成员,因此如果其成员被反序列化则不会。
第二个问题是您已将water_level_trend
声明为int
,但它在JSON中显示为空字符串:
"water_level_trend":"",
空字符串不能绑定到整数;如果您尝试,DataContractJsonSerializer
将抛出以下异常:
反序列化ApiRegionalne类型的对象时出错。值''无法解析为'Int32'类型。
由于您似乎希望使用数据合约属性明确标记类型,因此您可以使用网站https://jsonutils.com/为您自动生成类型,并应用所需的属性。你也可以选择自动驼峰你的属性和类型名称,然后使其符合推荐的.Net风格:
[DataContract]
public class Pagination
{
[DataMember(Name = "totalitems")]
public int Totalitems { get; set; }
[DataMember(Name = "itemsperpage")]
public int Itemsperpage { get; set; }
}
[DataContract]
public class Six // Fixed name from 6
{
[DataMember(Name = "id")]
public string Id { get; set; }
[DataMember(Name = "name")]
public string Name { get; set; }
[DataMember(Name = "city")]
public string City { get; set; }
[DataMember(Name = "slug_name")]
public string SlugName { get; set; }
}
[DataContract]
public class Provinces
{
[DataMember(Name = "6")]
public Six Six { get; set; }
}
[DataContract]
public class News
{
[DataMember(Name = "id")]
public string Id { get; set; }
[DataMember(Name = "title")]
public string Title { get; set; }
[DataMember(Name = "shortcut")]
public string Shortcut { get; set; }
[DataMember(Name = "content")]
public string Content { get; set; } // Fixed type from object
[DataMember(Name = "rso_alarm")]
public string RsoAlarm { get; set; }
[DataMember(Name = "rso_icon")]
public string RsoIcon { get; set; } // Fixed type from object
[DataMember(Name = "valid_from")]
public string ValidFrom { get; set; }
[DataMember(Name = "0")]
public string Zero { get; set; } // Fixed name from 0
[DataMember(Name = "valid_to")]
public string ValidTo { get; set; }
[DataMember(Name = "1")]
public string One { get; set; } // Fixed name from 1
#if false
// Removed since the correct type is unknown.
[DataMember(Name = "repetition")]
public object Repetition { get; set; }
#endif
[DataMember(Name = "longitude")]
public string Longitude { get; set; }
[DataMember(Name = "latitude")]
public string Latitude { get; set; }
[DataMember(Name = "water_level_value")]
public int WaterLevelValue { get; set; } // Fixed type to int
[DataMember(Name = "water_level_warning_status_value")]
public int WaterLevelWarningStatusValue { get; set; } // Fixed type to int
[DataMember(Name = "water_level_alarm_status_value")]
public int WaterLevelAlarmStatusValue { get; set; } // Fixed type to int
[DataMember(Name = "water_level_trend")]
public string WaterLevelTrend { get; set; } // This must remain a string since it appears as a non-numeric empty string in the JSON: "".
[DataMember(Name = "river_name")]
public string RiverName { get; set; }
[DataMember(Name = "location_name")]
public string LocationName { get; set; }
[DataMember(Name = "created_at")]
public string CreatedAt { get; set; }
[DataMember(Name = "2")]
public string Two { get; set; } // // Fixed name from 2
[DataMember(Name = "updated_at")]
public string UpdatedAt { get; set; }
[DataMember(Name = "3")]
public string Three { get; set; } // Fixed name from 3
[DataMember(Name = "type")]
public string Type { get; set; }
[DataMember(Name = "provinces")]
public Provinces Provinces { get; set; }
}
[DataContract]
public class ApiRegionalne
{
[DataMember(Name = "pagination")]
public Pagination Pagination { get; set; }
[DataMember(Name = "newses")]
public IList<News> Newses { get; set; }
}
请注意,有必要对自动生成的类型进行一些手动修复,例如将数字属性重命名为某些适当的非数字名称,例如: 1
到One
。此外,有必要将JSON中某些属性的类型从object
更改为更合适的属性,例如string
。上面对手动更改进行了评论。