我希望能够将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以这种方式序列化对象?如果没有,我怎么能做到这一点?感谢。
感谢@ Hightechrider的回答,我能够编写一些解决问题的代码。
您可以在此处查看工作示例https://gist.github.com/1153155
答案 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;}
}