2017-09-19 1 views
2

Je suis en train de désérialiser le fichier JSON suivant: http://komunikaty.tvp.pl/komunikatyxml/malopolskie/wszystkie/0?_format=jsonComment désérialiser tableau JSON en C#

Mon code 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); 

Et mes cours:

[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; 
} 

Le JSON désérialiseur ne jette aucune exception, mais mes données sont néanmoins nulles.

Qu'est-ce que je fais mal?

+1

Alternativement, vous pouvez essayer avec la méthode Newtonsoft.Json JsonConvert.DeserializeObject – Amit

Répondre

2

Votre problème de base est que l'opt-in serializers contrat de données (à la fois DataContractSerializer et DataContractJsonSerializer) sont . Si vous marquez un type avec [DataContract] vous devez également marquer les membres à sérialisés avec [DataMember], comme expliqué dans Using Data Contracts:

Vous pouvez également créer explicitement un contrat de données en utilisant DataContractAttribute et DataMemberAttribute attributs. Cela est normalement effectué en appliquant l'attribut DataContractAttribute au type. Cet attribut peut être appliqué aux classes, structures et énumérations. L'attribut DataMemberAttribute doit ensuite être appliqué à chaque membre du type de contrat de données pour indiquer qu'il s'agit d'un membre de données, c'est-à-dire qu'il doit être sérialisé.

Vous n'avez pas appliqué [DataMember] à l'un des membres de votre type newses, donc pas si ses membres sont désérialisée.

Un deuxième problème est que vous avez déclaré water_level_trend comme int, mais il apparaît comme une chaîne vide dans le JSON:

 "water_level_trend":"", 

Une chaîne vide ne peut pas être lié à un nombre entier; Si vous essayez, DataContractJsonSerializer lèvera l'exception suivante:

Une erreur s'est produite lors de la désérialisation de l'objet de type ApiRegionalne. La valeur '' ne peut pas être analysée comme le type 'Int32'.

Puisque vous semblez vouloir marquer explicitement vos types d'attributs contrat de données, vous pouvez utiliser le site https://jsonutils.com/ pour générer automatiquement vos types pour vous avec les attributs souhaités appliqués. Vous pouvez également choisir de automatiquement camel cas vos noms de propriété et le type, ce qui porte alors en conformité avec le style .Net recommandé:

[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; } 
} 

Notez qu'il était nécessaire de faire des corrections manuelles aux types générés automatiquement tels que renommer les propriétés numériques en un nom non numérique approprié, par exemple 1 à One. En outre, il était nécessaire de changer les types de certaines propriétés qui étaient null dans le JSON de object à quelque chose de plus approprié comme string. Les modifications manuelles sont commentées ci-dessus.

2

Vous devez marquer tous les domaines publics de la classe newses comme faisant partie du contrat:

[DataContract] 
public class newses 
{ 
    [DataMember(Name = "id")] //This is what you need to add 
    public int id; 

    //Do the same for all other fields   
}