如何在c#中反序列化json数组

时间:2017-09-19 16:59:00

标签: c# .net json

我正在尝试反序列化以下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反序列化器不会抛出任何异常,但我的数据仍为空。

我做错了什么?

2 个答案:

答案 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)

您的基本问题是数据合约序列化程序(DataContractSerializerDataContractJsonSerializer选择加入。如果您使用[DataContract]标记类型,则还必须使用[DataMember]标记要序列化的成员,如Using Data Contracts中所述:

  

您还可以使用DataContractAttributeDataMemberAttribute属性明确创建数据合同。这通常通过将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; }
}

请注意,有必要对自动生成的类型进行一些手动修复,例如将数字属性重命名为某些适当的非数字名称,例如: 1One。此外,有必要将JSON中某些属性的类型从object更改为更合适的属性,例如string。上面对手动更改进行了评论。