Newtonsoft的Json.Net用到最後,難免會基於安全或頻寬等需求,要將某些資料物件(ORM)的某屬性隱藏起來,不在序列化階段將其序列化並輸出。這篇文章就是要討論這個情況下的實作問題。
其實要隱藏屬性,Json.Net有提供許多簡單的作法,例如冠上[JsonIgnore]Attrubute就是一個非常直觀的做法。
public class Customer { [JsonIgnore] //加上這個屬性就會隱藏了 public int CustId {get; set;} public string FirstName {get; set;} }
Json.Net還有另外提供一個半動態的做法稱為有條件的屬性序列化(Conditional Property Serialization),序列化階段利用反射取得方法名稱(過濾掉ShouldSerialize字串)後再去對應屬性,執行判斷是否要進行該屬性的序列化,非常屌。詳情請看:ShouldSerialize
public class Employee { public string Name { get; set; } public Employee Manager { get; set; } //如果Manager不是自己物件本身,就顯示這個屬性 public bool ShouldSerializeManager() { return (Manager != this); } }
上面舉例的靜態與半動態的做法,在後端實務上仍然有力有未逮之處,因此,我們又得搬出DefaultContractResolver出來練兵了。
public class JsonHiddenProperties : Newtonsoft.Json.Serialization.DefaultContractResolver { /// <summary> /// 要隱藏的屬性名稱(字串陣列) /// </summary> public string[] aryHidden { get; set; } = new string[] { }; public JsonHiddenProperties() { } protected override System.Collections.Generic.IList<Newtonsoft.Json.Serialization.JsonProperty> CreateProperties(System.Type oType, Newtonsoft.Json.MemberSerialization oMS) { var oJP = base.CreateProperties(oType, oMS); //實作LINQ NOT IN return oJP.Where(x => !aryHidden.Contains(x.PropertyName)).ToList(); } }
程式碼的工作原理很簡單,大致上就是你給我黑名單,我在序列化時期如果有看到不再黑名單內的屬性就往外丟(序列化),當然沒往外丟的就胎死腹中了(隱藏)。
套用方式很簡單,請參考下列的程式碼,你懂得!
public static void Main() { Employee oEmployee = new Employee(); oEmployee.cNameFirst = "John1"; oEmployee.cNameMiddle = "John2"; //這個在序列化後會消失 oEmployee.cNameLast = "John3"; Console.WriteLine( Newtonsoft.Json.JsonConvert.SerializeObject( oEmployee, Newtonsoft.Json.Formatting.None, new Newtonsoft.Json.JsonSerializerSettings { ContractResolver = new JsonHiddenProperties() { aryHidden = new[] { "cNameMiddle" } }} ) ); } public class Employee { public string cNameFirst { get; set; } public string cNameMiddle { get; set; } public string cNameLast { get; set; } }