2015-08-13 2 views
1

Cela semble être la même question que ci-dessous, mais cette réponse n'a pas résolu le:Comment puis-je sérialiser un tableau de chaînes en JSON à l'aide de DataContractJsonSerializer?

Deserializing a Simple JSON Array

J'utilise DataContractJsonSerializer convertir XML en JSON et vice versa. Tout fonctionne avec des types de données complexes et des tableaux de types de données complexes, mais j'ai un problème pour produire un JSON pour un tableau de chaînes.

Le JSON je dois produire devrait avoir cette structure:

{ 
    "data": { 
    "x_axis": { 
     "labels": [ "Jan", "Feb", "Mar", "Apr","May", "Jun", "Jul", Aug","Sep", Oct", "Nov", "Dec" ] 
    } 
    } 
} 

Les objets que je me sers sont: -

LineChartData:

[DataContract] 
public class LineChartData 
{ 
    [DataMember(Name = "x_axis")] 
    public LineChartXAxis XAxis { get; set; } 
} 

LineChartXAxis:

[DataContract] 
public class LineChartXAxis 
{ 
    [DataMember(Name = "labels")] 
    public string[] Labels { get; set; } 
} 

Le XML que je suis en train de convertir ressemble à ceci:

<LineChartData> 
    <XAxis> 
    <Labels>Jan</Labels> 
    <Labels>Feb</Labels> 
    <Labels>Mar</Labels> 
    <Labels>Apr</Labels> 
    <Labels>May</Labels> 
    <Labels>Jun</Labels> 
    <Labels>Jul</Labels> 
    <Labels>Aug</Labels> 
    <Labels>Sep</Labels> 
    <Labels>Oct</Labels> 
    <Labels>Nov</Labels> 
    <Labels>Dec</Labels> 
    </XAxis> 
</LineChartData> 

Mon code deserialising est:

var serialiser = new XmlSerializer(typeof(LineChartData)); 
var stringReader = new StringReader(xml); 

var result = serialiser.Deserialize(stringReader); 

Le JSON je reviens a toujours un tableau vide étiquettes:

{ 
    "data": { 
    "x_axis": { 
     "labels":[] 
    } 
    } 
} 

Comment dois-je définir la propriété Labels dans LineChartXAxis pour sérialiser le JSON correctement?

Répondre

1

Vous avez une questions couple ici:

  1. Votre collection <Labels> ne dispose pas d'un élément de récipient extérieur. Par défaut, XmlSerializer ajoute un élément conteneur lors de la sérialisation d'une collection. Pour ignorer l'élément wrapper externe, ajoutez un attribut [XmlElement("Labels")] à la propriété Labels. (XML serializer attributes et data contract attributes sont mutuellement indépendantes et peuvent être appliquées l'une et l'autre sans que l'une n'entrave l'autre.)

    I.e. votre problème actuel est en lisant votre liste de chaînes de XML n'écrivant pas alors à JSON. Votre JSON a un élément racine externe correspondant à l'objet {"data": {...}}. Vous devez en tenir compte lors de la sérialisation. (Peut-être que vous faites et ce n'est pas montré.)

Ainsi les éléments suivants devraient fonctionner:

[DataContract] 
public class LineChartData 
{ 
    [DataMember(Name = "x_axis")] 
    public LineChartXAxis XAxis { get; set; } 
} 

[DataContract] 
public class LineChartXAxis 
{ 
    [DataMember(Name = "labels")] 
    [XmlElement("Labels")] 
    public string[] Labels { get; set; } 
} 

[DataContract] 
public class RootObject<T> 
{ 
    [DataMember(Name = "data")] 
    public T Data { get; set; } 
} 

public static class RootObjectExtensions 
{ 
    public static RootObject<T> FromData<T>(T data) 
    { 
     return new RootObject<T> { Data = data }; 
    } 
} 

Et puis les utiliser comme

 var data = xmlString.LoadFromXML<LineChartData>(); 
     var jsonString = DataContractJsonSerializerHelper.GetJson(RootObjectExtensions.FromData(data)); 

Avec des méthodes d'extension:

public static class XmlSerializerHelper 
{ 
    public static T LoadFromXML<T>(this string xmlString, XmlSerializer serial = null) 
    { 
     using (StringReader reader = new StringReader(xmlString)) 
     { 
      object result = (serial ?? new XmlSerializer(typeof(T))).Deserialize(reader); 
      if (result is T) 
       return (T)result; 
     } 
     return default(T); 
    } 
} 

public static class DataContractJsonSerializerHelper 
{ 
    public static string GetJson<T>(T obj, DataContractJsonSerializer serializer = null) 
    { 
     using (var memory = new MemoryStream()) 
     { 
      (serializer ?? new DataContractJsonSerializer(typeof(T))).WriteObject(memory, obj); 
      memory.Seek(0, SeekOrigin.Begin); 
      using (var reader = new StreamReader(memory)) 
      { 
       return reader.ReadToEnd(); 
      } 
     } 
    } 
} 

Soit dit en passant, comme une alternative, vous pouvez regarder Json.NET, qui a la capacité de convert directly between JSON and XML.

+0

dbc, cet attribut XmlElement était exactement ce dont j'avais besoin. Merci pour votre réponse. J'ai laissé le reste de mon code inchangé, sans les méthodes d'extension, car il fonctionne maintenant parfaitement. –

+0

Nous avons pris la décision d'utiliser les bibliothèques .NET natives à la place de Json.NET, ce qui explique pourquoi je le fais avec DataContractSerializer, mais j'utilise Json.NET pour tester et déboguer et c'est comme ça que j'ai créé XML que j'utilise pour tester, sachant qu'il devrait produire le JSON requis. –

-1

Les tableaux traditionnels ne sont pas facilement redimensionnés et je pense que c'est la raison pour laquelle le sérialiseur a des problèmes. Changez votre propriété Labels pour qu'elle soit un List<string> à la place et cela devrait fonctionner.

+0

viggity, merci pour la réponse. J'ai essayé cela et cela n'a toujours pas fonctionné, donc ça ne semble pas être la structure du tableau qui est le problème dans ce cas. –