如何将List <t>转换为特定的Json格式</t>

时间:2011-08-17 02:22:12

标签: c# json serialization

我希望能够将List<T>转换为特定的JSON表格式。在我的例子中,T将始终是一个简单的对象(没有嵌套属性)。这里有两个例子来说明我想要的东西。

示例#1:List<Person>到JSON

// C# list of Persons
var list = new List<Person>() {
  new Person() { First = "Jesse", Last = "Gavin", Twitter = "jessegavin" },
  new Person() { First = "John", Last = "Sheehan", Twitter = "johnsheehan" }
};

// I want to transform the list above into a JSON object like so
{
  columns : ["First", "Last", "Twitter"],
  rows: [
    ["Jesse", "Gavin", "jessegavin"],
    ["John", "Sheehan", "johnsheehan"]
  ]
}

示例#2:List<Address>到JSON

// C# list of Locations
var list = new List<Location>() {
  new Location() { City = "Los Angeles", State = "CA", Zip = "90210" },
  new Location() { City = "Saint Paul", State = "MN", Zip = "55101" },
};

// I want to transform the list above into a JSON object like so
{
  columns : ["City", "State", "Zip"],
  rows: [
    ["Los Angeles", "CA", "90210"],
    ["Saint Paul", "MN", "55101"]
  ]
}

有没有办法告诉JSON.net以这种方式序列化对象?如果没有,我怎么能做到这一点?感谢。

UPDATE:

感谢@ Hightechrider的回答,我能够编写一些解决问题的代码。

您可以在此处查看工作示例https://gist.github.com/1153155

3 个答案:

答案 0 :(得分:2)

使用反射,您可以获得该类型的属性列表:

        var props = typeof(Person).GetProperties();

给定一个Person p的实例,你可以得到一个属性值的枚举:

        props.Select(prop => prop.GetValue(p, null))

用通用方法包装它们,添加你最喜欢的Json序列化,你就拥有了你想要的格式。

答案 1 :(得分:0)

假设你使用.Net 4,这应该做你想要的一切。该类实际上允许您转换为XML或JSON。 CommunicationType的Enum位于底部。如果您传递的类已经使用DataContract&amp; amp;来修饰,则序列化程序的效果最佳。 DataMember属性。我在底部加了一个样本。它也将采用匿名类型,只要它是所有简单类型。

反射也可以工作但是你必须理解输出复杂数据类型的所有JSON细微差别等。这使用.Net 4中的内置JSON序列化器。还有一点需要注意,因为JSON没有定义日期类型.Net将日期放在一个时髦的ASP.Net自定义格式中。只要使用内置的反序列化器进行反序列化,它就可以正常工作。如果你需要的话,我可以在那里挖掘文档。

using System;
using System.Xml.Serialization;
using System.Text;
using System.Runtime.Serialization.Json;
using System.IO;
using System.Xml.Linq;

internal class Converter
{

    public static string Convert<T>(T obj, CommunicationType format, bool indent = false, bool includetype = false)
    {
        if (format == CommunicationType.XML)
        {
            return ToXML<T>(obj, includetype, indent);
        }
        else if (format == CommunicationType.JSON)
        {
            return ToJSON<T>(obj);
        }
        else
        {
            return string.Empty;
        }

    }

    private static string ToXML<T>(T obj, bool includetype, bool indent = false)
    {
        if (includetype)
        {
            XElement xml = XMLConverter.ToXml(obj, null, includetype);

            if(indent) {
                return xml.ToString(); 
            }
            else
            { 
                return xml.ToString(SaveOptions.DisableFormatting);
            }

        }
        else
        {
            System.Xml.Serialization.XmlSerializerNamespaces ns = new System.Xml.Serialization.XmlSerializerNamespaces();
            XmlSerializer xs = new XmlSerializer(typeof(T));
            StringBuilder sbuilder = new StringBuilder();
            var xmlws = new System.Xml.XmlWriterSettings() { OmitXmlDeclaration = true, Indent = indent };

            ns.Add(string.Empty, string.Empty);

            using (var writer = System.Xml.XmlWriter.Create(sbuilder, xmlws))
            {
                xs.Serialize(writer, obj, ns);
            }

            string result = sbuilder.ToString();

            ns = null;
            xs = null;
            sbuilder = null;
            xmlws = null;

            return result;
        }
    }

    private static string ToJSON<T>(T obj)
    {
        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
        using (MemoryStream ms = new MemoryStream())
        {
            string result = string.Empty;
            System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();

            ser.WriteObject(ms, obj);
            result = encoding.GetString(ms.ToArray());

            ms.Close();
            encoding = null;
            ser = null;

            return result;
        }
    }

}

[DataContract()]
public enum CommunicationType : int
{
    [XmlEnum("0"), EnumMember(Value = "0")]
    XML = 0,

    [XmlEnum("1"), EnumMember(Value = "1")]
    JSON = 1
}

[DataContract(Namespace = "")]
public partial class AppData
{
    [DataMember(Name = "ID")]
    public string ID { get; set; }

    [DataMember(Name = "Key")]
    public string Key { get; set; }

    [DataMember(Name = "Value")]
    public string Value { get; set; }

    [DataMember(Name = "ObjectType")]
    public string ObjectType { get; set; }
}

答案 2 :(得分:-1)

您不需要标准格式的任何具体原因?

要真正回答这个问题:

由于这是JSON语法之外的东西,我想不出在默认框架中实现它的方法。

一种解决方案是利用属性来装饰您希望通过有线属性传输的属性,并使用Reflection循环遍历属性并输出其属性名称作为列标题,然后循环抛出对象并写入值。通用性足以使其可以应用于其他对象。

public class Location
{
     [JsonFooAttribute("City")]
     public string city {get;set;}
     [JsonFooAttribute("State")]
     public string state {get;set;}
}