【问题标题】:How to convert a List<T> to specific Json format如何将 List<T> 转换为特定的 Json 格式
【发布时间】:2011-08-18 10:36:29
【问题描述】:

我希望能够将 List&lt;T&gt; 转换为特定的 JSON 表格格式。在我的情况下,T 将始终是一个简单的对象(没有嵌套属性)。这里有两个例子来说明我想要什么。

示例 #1:List&lt;Person&gt; 转 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&lt;Address&gt; 转 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

【问题讨论】:

    标签: c# json serialization


    【解决方案1】:

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

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

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

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

    将它们包装在一个通用方法中,添加您最喜欢的 Json 序列化,然后您就拥有了您想要的格式。

    【讨论】:

      【解决方案2】:

      假设您使用 .Net 4,这应该可以满足您的所有需求。该类实际上允许您转换为 XML 或 JSON。 CommunicationType 的枚举位于底部。如果您传递的类已使用 DataContract 和 DataMember 属性进行修饰,则序列化程序效果最佳。我在底部包含了一个示例。只要都是简单类型,它也将采用匿名类型。

      反射也可以,但是您必须了解所有 JSON 的细微差别才能输出复杂的数据类型等。这使用了 .Net 4 中的内置 JSON 序列化程序。还有一点需要注意,因为 JSON 没有定义日期type .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; }
      }
      

      【讨论】:

      • 这并不能解决我在问题中写到的问题。
      【解决方案3】:

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

      要真正回答这个问题:

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

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

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

      【讨论】:

      • 这不能作为答案。这应该是评论。
      • 我问是因为通常当人们像这样离开公路时,更简单的解决方案大多数时间是它所绑定的元素或控件,需要进行调整。
      • @Mangesh - 我知道系统是如何工作的。快速查看我的帐户会发现我没有足够的“积分”来发表评论。参与对话的唯一方法是将其发布为答案。
      • @PIKER_32 我尝试使用这种格式的原因是因为它减少了通过网络传输的数据的大小。我有一个特殊情况,我需要将近 10,000 行数据绑定到基于 JavaScript 的网格(不是我选择的),这种格式会大大减少字节数。
      • 听起来好像给定的要求没有调用/允许分页?尽管试图减少传输开销,但您的推理是有道理的。
      猜你喜欢
      • 2014-02-05
      • 1970-01-01
      • 2019-04-13
      • 1970-01-01
      • 2017-05-06
      • 1970-01-01
      • 2019-02-03
      • 1970-01-01
      • 2010-11-18
      相关资源
      最近更新 更多