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

  

转载于:https://www.cnblogs.com/goodlucklzq/p/4448458.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值