zoukankan      html  css  js  c++  java
  • WebApi2官网学习记录---JSON与XML的序列化

    JSON序列化:

    WebAPI的默认序列库使用的是Json.NET,可以在Globally中配置使用DataContractJsonSerializer 进行序列化 

            protected void Application_Start()
            {
                GlobalConfiguration.Configure(WebApiConfig.Register);
                var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
                json.UseDataContractJsonSerializer = true;
            }

    默认情况下,所有的公共的属性和字段都能被序列化(非公共的不能),除非声明了JsonIgnore特性

    public class Product
    {
        public string Name { get; set; }
        public decimal Price { get; set; }
        [JsonIgnore]
        public int ProductCode { get; set; } // 不能被序列化
    }

    或者使用一下方式,将需要序列化的元素显示标出来

    [DataContract]
    public class Product
    {
        [DataMember]
        public string Name { get; set; }
        [DataMember]
        public decimal Price { get; set; }
        public int ProductCode { get; set; }  // 不能被序列化
    }

    JSON序列化时的一些设置【测试好像没效果,疑惑】

    1  var json =  GlobalConfiguration.Configuration.Formatters.JsonFormatter;
    2             //设置UTC时区
    3             json.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;
    4             //设置缩进
    5             json.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
    6             //使用驼峰命名法
    7             json.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    8             //使用Microsoft JSON 时间格式("/Date(ticks)/")
    9             json.SerializerSettings.DateFormatHandling= Newtonsoft.Json.DateFormatHandling.MicrosoftDateFormat;
    View Code

    action方法可以返回一个匿名对象,序列化成JSON(匿名对象不能序列化成XML)

     1 public object Get()
     2 {
     3     return new { 
     4         Name = "Alice", 
     5         Age = 23, 
     6         Pets = new List<string> { "Fido", "Polly", "Spot" } 
     7     };
     8 }
     9 结果:
    10 {"Name":"Alice","Age":23,"Pets":["Fido","Polly","Spot"]}

     如果从client收到一个JSON格式的对象,可以反序列化这个JSON对象成Newtonsoft.Json.Linq.JObject  类型的对象【需要时POST请求】

    public void Post(JObject person)
    {
        string name = person["Name"].ToString();
        int age = person["Age"].ToObject<int>();
    }

    Note:XML序列器不支持 匿名对象和JObject实例

    XML序列化: 

    默认使用DataContractSerializer进行xml序列化,序列化的规则如下:

    • 所有的公共属性和字段都能被序列化,使用IgnoreDataMember 特性可以将其排除 
    • 私有和受保护的成员不会被序列化
    • 只读属性不会被序列化
    • 类和成员的名字被原样写入xml
    • 使用默认的xml命名空间

    如果要更准确的控制序列化的内容,可以使用DataContract 特性,当出现了这个特性,将按如下规则进行序列化:

    • 只有标记了DataMember特性的字段或属性才能被序列化
    • 标记了DataMember特性的private/protected的成员也能被序列化
    • 只读属性不会被序列化
    • 改变对应的xml文件中命名空间或类的名字,使用DataContract特性
                //xml默认使用DataContractSerializer 进行序列化
                var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
                xml.UseXmlSerializer = true;  //使用XmlSerializer 进行序列化
                xml.Indent = true;//使用缩进
                //设置指定对象使用指定的序列化器
                xml.SetSerializer<Product>(new XmlSerializer(typeof(Product)));

    移除JSON或XML序列化器    

    void ConfigureApi(HttpConfiguration config)
    {
        // Remove the JSON formatter
        config.Formatters.Remove(config.Formatters.JsonFormatter);
    
        // or
    
        // Remove the XML formatter
        config.Formatters.Remove(config.Formatters.XmlFormatter);
    }

    处理对象的循环引用

       默认情况下XML和JSON的序列化器会对对象的循环引用这种情况在序列化时抛出异常

       JSON可以使用如下方式处理:  

    var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
    json.SerializerSettings.PreserveReferencesHandling = 
        Newtonsoft.Json.PreserveReferencesHandling.All;

    举例如下:

     1 public class Employee
     2 {
     3     public string Name { get; set; }
     4     public Department Department { get; set; }
     5 }
     6 
     7 public class Department
     8 {
     9     public string Name { get; set; }
    10     public Employee Manager { get; set; }
    11 }
    12 
    13 public class DepartmentsController : ApiController
    14 {
    15     public Department Get(int id)
    16     {
    17         Department sales = new Department() { Name = "Sales" };
    18         Employee alice = new Employee() { Name = "Alice", Department = sales };
    19         sales.Manager = alice;
    20         return sales;
    21     }
    22 }
    23 结果:
    24 {"$id":"1","Name":"Sales","Manager":{"$id":"2","Name":"Alice","Department":{"$ref":"1"}}}
    View Code

      XML有两种方式处理这种情况:

    1. 在DataContract特性上设置IsReference=true                  
    1 [DataContract(IsReference=true)]
    2 public class Department
    3 {
    4     [DataMember]
    5     public string Name { get; set; }
    6     [DataMember]
    7     public Employee Manager { get; set; }
    8 }
    View Code

          2.创建一个针对这个对象的xml序列化器,设置允许循环引用        

    1 var xml = GlobalConfiguration.Configuration.Formatters.XmlFormatter;
    2 var dcs = new DataContractSerializer(typeof(Department), null, int.MaxValue, 
    3     false, /* preserveObjectReferences: */ true, null);
    4 xml.SetSerializer<Department>(dcs);
    View Code

    测试对象的序列化 

     1 string Serialize<T>(MediaTypeFormatter formatter, T value)
     2 {
     3     // Create a dummy HTTP Content.
     4     Stream stream = new MemoryStream();
     5     var content = new StreamContent(stream);
     6     /// Serialize the object.
     7     formatter.WriteToStreamAsync(typeof(T), value, stream, content, null).Wait();
     8     // Read the serialized string.
     9     stream.Position = 0;
    10     return content.ReadAsStringAsync().Result;
    11 }
    12 
    13 T Deserialize<T>(MediaTypeFormatter formatter, string str) where T : class
    14 {
    15     // Write the serialized string to a memory stream.
    16     Stream stream = new MemoryStream();
    17     StreamWriter writer = new StreamWriter(stream);
    18     writer.Write(str);
    19     writer.Flush();
    20     stream.Position = 0;
    21     // Deserialize to an object of type T
    22     return formatter.ReadFromStreamAsync(typeof(T), stream, null, null).Result as T;
    23 }
    24 
    25 // Example of use
    26 void TestSerialization()
    27 {
    28     var value = new Person() { Name = "Alice", Age = 23 };
    29 
    30     var xml = new XmlMediaTypeFormatter();
    31     string str = Serialize(xml, value);
    32 
    33     var json = new JsonMediaTypeFormatter();
    34     str = Serialize(json, value);
    35 
    36     // Round trip
    37     Person person2 = Deserialize<Person>(json, str);
    38 }
    View Code

      

  • 相关阅读:
    Github Actions 中 Service Container 的使用
    EFCore 5 新特性 SaveChangesInterceptor
    使用 Xunit.DependencyInjection 改造测试项目
    WeihanLi.Npoi 1.11.0/1.12.0 Release Notes
    新版本 swagger 组件中 Servers 的 坑
    JDBC 规范中文版 4.2- 第五章 类和接口
    JDBC 规范中文版 4.2 -第四章 概览
    JDBC 规范中文版 4.2 -第三章 新特性
    JDBC 规范中文版 4.2 -第二章 目标
    Serve static assets with an efficient cache policy
  • 原文地址:https://www.cnblogs.com/goodlucklzq/p/4448458.html
Copyright © 2011-2022 走看看