一、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<Area>();
}
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<Area> 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<Area> 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<Area> 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
}
]
更多: