【问题标题】:Serialize in a human readable text format以人类可读的文本格式序列化
【发布时间】:2008-11-03 14:25:02
【问题描述】:

.NET 2.0 (C#) 中是否有一种方法可以像使用 XmlSerializer 以简单/可定制的人类可读格式(例如看起来像 PXLS 或 JSON)一样序列化对象? 我也知道 XML 是人类可读的,我正在寻找一些冗余较少的东西,你可以将结果输出到控制台以供用户使用。

【问题讨论】:

    标签: c# .net serialization .net-2.0


    【解决方案1】:

    要在 .NET 中序列化为 JSON,请执行以下操作:

    public static string ToJson(IEnumerable collection)
            {
                DataContractJsonSerializer ser = new DataContractJsonSerializer(collection.GetType());
                string json;
                using (MemoryStream m = new MemoryStream())
                {
                    XmlDictionaryWriter writer = JsonReaderWriterFactory.CreateJsonWriter(m);
                    ser.WriteObject(m, collection);
                    writer.Flush();
    
                    json = Encoding.Default.GetString(m.ToArray());
                }
                return json;
            }
    

    集合项需要具有“DataContract”属性,并且您希望序列化为 JSON 的每个成员都必须具有“DataMember”属性。

    这可能仅适用于 .NET 3.5。但是 2.0 也有一个同样简单的版本...

    【讨论】:

    • 几分钟前通过使用Json.NET,我发现JSON 不是最好的方法,因为它不支持枚举。结果是一个人类也不太可读的数字。
    • Okej,好吧,实现完全取决于您要序列化的内容。如果它只是一种成员很少的类型,为什么不直接覆盖“ToString”并以您想要的任何格式返回 string.Format
    【解决方案2】:

    我在这里找到了一份详尽的文档:

    http://pietschsoft.com/post/2008/02/NET-35-JSON-Serialization-using-the-DataContractJsonSerializer.aspx

    使用这个有用的类(支持泛型)

    using System.Runtime.Serialization;
    using System.Runtime.Serialization.Json;
    
    public class JSONHelper
    {
      public static string Serialize<T>(T obj)
      {
          DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
          MemoryStream ms = new MemoryStream();
          serializer.WriteObject(ms, obj);
          string retVal = Encoding.Default.GetString(ms.ToArray());
          ms.Dispose();
          return retVal;
      }
    
      public static T Deserialize<T>(string json)
      {
          T obj = Activator.CreateInstance<T>();
          MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(json));
          DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
          obj = (T)serializer.ReadObject(ms);
          ms.Close();
          ms.Dispose();
          return obj;
      }
    }
    

    【讨论】:

    • 使用Encoding.Default 不适用于非ASCII 文本,因为DataContractJsonSerializer.WriteObject 的(未记录的)实现使用硬编码的Encoding.UTF8
    【解决方案3】:

    .Net 的内置序列化选项是 Xml、Xml-Soap 和二进制。既然你已经排除了 xml 和二进制绝对不是人类可读的,你就必须自己动手。

    当你自己滚动时,你有几个选择:

    • 向类添加实用程序或扩展方法,如建议的 AviewAnew
    • 扩展 System.Runtime.Serialization.Formatter / 实施 System.Runtime.Serialization.IFormatter
    • 通过 google 在线查找通用组件,它可以满足您的需求。

    请注意,第二项可以专门针对您的特定班级(如果您不希望,它不必能够处理任何班级)并且后两项不是互斥的。

    我过去曾搜索过 .Net JSON 格式化程序,而且肯定有多种选择。然而,那次我最终走向了不同的方向。我只是对他们中的任何一个都没有信心。也许其他人可以提供更具体的建议。 JSON 变得足够大,希望微软很快会在框架中包含对它的“本机”支持。

    【讨论】:

    • 我可以编写自己的 HumanSerializer 来反映给它的对象类型——但这会消耗太多时间。我认为以前可能已经有人解决了这个问题 - 但谷歌没有找到他或她。
    【解决方案4】:

    https://stackoverflow.com/a/38538454/6627992

    您可以使用以下标准方法来获取格式化的 Json

    JsonReaderWriterFactory.CreateJsonWriter(Stream stream, Encoding encoding, bool ownsStream, bool indent, string indentChars)

    只设置"indent==true"

    试试这样的

        public readonly DataContractJsonSerializerSettings Settings = 
                new DataContractJsonSerializerSettings
                { UseSimpleDictionaryFormat = true };
    
        public void Keep<TValue>(TValue item, string path)
        {
            try
            {
                using (var stream = File.Open(path, FileMode.Create))
                {
                    var currentCulture = Thread.CurrentThread.CurrentCulture;
                    Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
    
                    try
                    {
                        using (var writer = JsonReaderWriterFactory.CreateJsonWriter(
                            stream, Encoding.UTF8, true, true, "  "))
                        {
                            var serializer = new DataContractJsonSerializer(type, Settings);
                            serializer.WriteObject(writer, item);
                            writer.Flush();
                        }
                    }
                    catch (Exception exception)
                    {
                        Debug.WriteLine(exception.ToString());
                    }
                    finally
                    {
                        Thread.CurrentThread.CurrentCulture = currentCulture;
                    }
                }
            }
            catch (Exception exception)
            {
                Debug.WriteLine(exception.ToString());
            }
        }
    

    注意线条

        var currentCulture = Thread.CurrentThread.CurrentCulture;
        Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
        ....
        Thread.CurrentThread.CurrentCulture = currentCulture;
    

    您应该使用 InvariantCulture 以避免在具有不同区域设置的计算机上反序列化期间出现异常。例如,doubleDateTime 的格式无效有时会导致它们。

    用于反序列化

        public TValue Revive<TValue>(string path, params object[] constructorArgs)
        {
            try
            {
                using (var stream = File.OpenRead(path))
                {
                    var currentCulture = Thread.CurrentThread.CurrentCulture;
                    Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
    
                    try
                    {
                        var serializer = new DataContractJsonSerializer(type, Settings);
                        var item = (TValue) serializer.ReadObject(stream);
                        if (Equals(item, null)) throw new Exception();
                        return item;
                    }
                    catch (Exception exception)
                    {
                        Debug.WriteLine(exception.ToString());
                        return (TValue) Activator.CreateInstance(type, constructorArgs);
                    }
                    finally
                    {
                        Thread.CurrentThread.CurrentCulture = currentCulture;
                    }
                }
            }
            catch
            {
                return (TValue) Activator.CreateInstance(typeof (TValue), constructorArgs);
            }
        }
    

    谢谢!

    【讨论】:

      【解决方案5】:

      将 xsl 应用到您的 xml 以去除您不想看到的内容?

      类似

      <?xml version="1.0"?>
      <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      <xsl:output method="text" indent="yes"/>
        <xsl:template match="*">
            <xsl:value-of select="name()" /><xsl:text>
      </xsl:text>
            <xsl:apply-templates select="@*"/>
      <xsl:apply-templates select="*"/>
        </xsl:template>
        <xsl:template match="@*|text()|comment()|processing-instruction">
         <xsl:value-of select="name()" />:<xsl:value-of select="." /><xsl:text>
      </xsl:text>
        </xsl:template>
      </xsl:stylesheet>
      

      【讨论】:

        猜你喜欢
        • 2015-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-09
        • 2021-05-11
        相关资源
        最近更新 更多