如何使用DataContractJsonSerializer将字符串数组序列化为JSON?

时间:2015-08-13 17:15:49

标签: c# arrays json datacontractserializer

这似乎与下面的问题相同,但答案尚未解决:

Deserializing a Simple JSON Array

我正在使用DataContractJsonSerializer将XML转换为JSON,反之亦然。一切都适用于复杂的数据类型和复杂数据类型的数组,但我遇到了为字符串数组生成JSON的问题。

我需要生成的JSON应该具有以下结构:

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

我使用的对象是: -

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

我想要转换的XML看起来像这样:

<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>

我的反序列化代码是:

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

var result = serialiser.Deserialize(stringReader);

我回来的JSON总是有一个空的标签数组:

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

如何在LineChartXAxis中定义Labels属性以正确序列化JSON?

2 个答案:

答案 0 :(得分:1)

这里有几个问题:

  1. 您的<Labels>集合没有外部容器元素。默认情况下,XmlSerializer在序列化集合时添加容器元素。要跳过外部包装器元素,请向[XmlElement("Labels")]属性添加Labels属性。 (XML serializer attributesdata contract attributes相互独立,可以在没有一组影响另一套的情况下应用。)

    即。你的实际问题是从XML中读取你的字符串列表而不是写入JSON。

  2. 您的JSON具有与{"data": {...}}对象对应的外部根元素。序列化时需要考虑到这一点。 (也许你这样做,但没有显示。)

  3. 因此以下内容应该有效:

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

    然后像

    一样使用它们
            var data = xmlString.LoadFromXML<LineChartData>();
            var jsonString = DataContractJsonSerializerHelper.GetJson(RootObjectExtensions.FromData(data));
    

    使用扩展方法:

    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();
                }
            }
        }
    }
    

    顺便提一下,作为替代方案,您可以查看具有Json.NET能力的convert directly between JSON and XML

答案 1 :(得分:-1)

传统阵列不容易调整大小,我认为这就是串行器出现问题的原因。将您的Labels属性更改为List<string>,这应该有效。