本文共 3900 字,大约阅读时间需要 13 分钟。
一、JavaScriptSerializer
JavaScriptSerializer是ASP.Net 自带的JSON序列化和反序列化工具,例如:MVC中的JsonResult也是使用的它。
位于:程序集 System.Web.Extensions 中
namespace System.Web.Script.Serialization{ // // 摘要: // 为启用 AFAX 的应用程序提供序列化和反序列化功能。 public class JavaScriptSerializer二、[ScriptIgnore] 用于指定在序列化对象时忽略的属性
特别说明:如果该属性在父类中重写,需要在父类中的属性重新指定。
namespace System.Web.Script.Serialization{ // // 摘要: // 指定 System.Web.Script.Serialization.JavaScriptSerializer 不序列化公共属性或公共字段。 此类不能被继承。 [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false, Inherited = true)] public sealed class ScriptIgnoreAttribute : Attribute {三、EF中json序列化的循环引用
1.在表关联显示指定主外键关系中会出现循环引用问题
2.在表自连接的主外键关系中会出现循环引用问题
3.在EF中指定[ScriptIgnore],需要去掉属性的virtual关键词,以为从数据库查处来的对象时继承关系的动态对象。
4.特别说明:在EF中的一对多关联列表的virtual关键词,则获取关联表数据失败。所以对于自引用类如果使用JavaScriptSerializer序列化去掉向下查找列表的功能
以自引用为实例说明:
实体类:
[Table("Area")]public partial class Area{ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] public Area() { Children = new HashSet(); } public int AreaID { get; set; } [Required] [StringLength(20)] public string AreaName { get; set; } public int? ParentID { get; set; } public int? SortValue { get; set; } public int AreaLevel { get; set; } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] [ScriptIgnore] public ICollection Children { get; set; } //特别说明:如果向下集合去掉virtual,向下查询将不可用 [ScriptIgnore] [ForeignKey("ParentID")] public Area ParentModel { get; set; } //特别说明:如果使用[ScriptIgnore] 需要去掉virtual声明}测试代码:
static void EfTest1(){ Test1 _context = new Test1(); JavaScriptSerializer _ser = new JavaScriptSerializer(); //获取省 Area province = _context.Areas.FirstOrDefault(q => q.AreaLevel == 1); Console.WriteLine(_ser.Serialize(province)); //获取省下的市 List cities = province.Children.ToList(); Console.WriteLine(cities.Count); Console.WriteLine(_ser.Serialize(cities)); //获取市 Area city = _context.Areas.FirstOrDefault(q => q.AreaLevel == 2); Console.WriteLine(_ser.Serialize(city)); //获取市所在的省 Area province2 = city.ParentModel; Console.WriteLine(_ser.Serialize(province2));}四、对于EF中的Json序列化推荐使用Newtonsoft
原因:Newtonsoft中提供了忽略循环引用的处理,枚举定义:ReferenceLoopHandling.Ignore,
这样就不需要修改实体类的代码,并且向下查找列表也可用。
static void EfTest2(){ Test1 _context = new Test1(); JsonSerializerSettings settings = new JsonSerializerSettings(); settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; //获取省 Area province = _context.Areas.FirstOrDefault(q => q.AreaLevel == 1); Console.WriteLine(JsonConvert.SerializeObject(province, settings)); //获取省下的市 List cities = province.Children.ToList(); Console.WriteLine(JsonConvert.SerializeObject(cities, settings)); //获取市 Area city = _context.Areas.FirstOrDefault(q => q.AreaLevel == 2); Console.WriteLine(JsonConvert.SerializeObject(cities, settings)); //获取市所在的省 Area province2 = city.ParentModel; Console.WriteLine(JsonConvert.SerializeObject(province2, settings));}
获取省对象结果:对象类型
{ "Children": [ { "Children": [], "AreaID": 2, "AreaName": "济南市", "ParentID": 1, "SortValue": null, "AreaLevel": 2 } ], "ParentModel": null, "AreaID": 1, "AreaName": "山东省", "ParentID": null, "SortValue": null, "AreaLevel": 1}获取省下的市列表:数组类型
[ { "Children": [], "ParentModel": { "Children": [], "ParentModel": null, "AreaID": 1, "AreaName": "山东省", "ParentID": null, "SortValue": null, "AreaLevel": 1 }, "AreaID": 2, "AreaName": "济南市", "ParentID": 1, "SortValue": null, "AreaLevel": 2 }]
更多: