EF 序列化实体为Json时的循环引用问题(不用自己写实体,不用匿名类型,不用EF的上下文属性)

自己写实体可以完美解决这个问题。(支持时间格式自定义)

用匿名类型也可以。

设置上下文方法如下:

(jz为数据库上下文对象)

jz.Configuration.ProxyCreationEnabled = false;
jz.Configuration.LazyLoadingEnabled = false;

不用这个的原因是Virtual属性也会生成。(只是占个位,[]里面没内容,但看着不爽)

我采用的方法是过滤掉Virtual属性的方法:

一个基于Json.net的类

1
using Newtonsoft.Json;<br>using Newtonsoft.Json.Converters;<br>using Newtonsoft.Json.Serialization;<br>using System;<br>using System.Collections.Generic;<br>using System.Linq;<br>using System.Reflection;<br>using System.Web;<br><br>namespace AceepSystem.Models.Help<br>{<br>    public class JsonForEF : DefaultContractResolver<br>    {<br>        string[] props = null;<br><br>        bool retain;<br><br>        /// <summary><br>        /// 构造函数<br>        /// </summary><br>        /// <param name="props">传入的属性数组</param><br>        /// <param name="retain">true:表示props是需要保留的字段  false:表示props是要排除的字段</param><br>        public JsonForEF(string[] props, bool retain = true)<br>        {<br>            //指定要序列化属性的清单<br>            this.props = props;<br><br>            this.retain = retain;<br>        }<br><br>        protected override IList<JsonProperty> CreateProperties(Type type,<br><br>        MemberSerialization memberSerialization)<br>        {<br>            IList<JsonProperty> list =<br>            base.CreateProperties(type, memberSerialization);<br>            //只保留清单有列出的属性<br>            return list.Where(p =><br>            {<br>                if (retain)<br>                {<br>                    return props.Contains(p.PropertyName);<br>                }<br>                else<br>                {<br>                    return !props.Contains(p.PropertyName);<br>                }<br>            }).ToList();<br>        }<br>        public static string[] GetVirtualList<T>()<br>        {<br>            var stringType = typeof(T);<br>            var props = stringType.GetProperties();<br>            List<string> test = new List<string>();<br>            foreach (var prop in props)<br>            {<br>                if (prop.GetAccessors()[0].IsVirtual)<br>                {<br>                    test.Add(prop.Name);<br>                }<br>            }<br>            return test.ToArray();<br>        }<br>        public static JsonSerializerSettings GetJsonConfig<T>()<br>        {<br><br>            JsonSerializerSettings jsetting = new JsonSerializerSettings();//过滤掉ef中的导航属性,无残留...<br>            jsetting.ContractResolver = new JsonForEF(<br>            JsonForEF.GetVirtualList<T>()//泛型方法传入当前要序列化的类型<br>            , false);//false为要排除的属性,true为要保留的属性(第一个参数为string[])<br>            jsetting.Converters.Add(new MyDateTimeConvertor());<br>            return jsetting;<br>        }<br>        public class MyDateTimeConvertor : DateTimeConverterBase<br>        {<br>            public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)<br>            {<br>                return DateTime.Parse(reader.Value.ToString());<br>            }<br><br>            public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)<br>            {<br>                writer.WriteValue(((DateTime)value).ToString("yyyy/MM/dd HH:mm"));<br>            }<br>        }<br>    }<br>}

 和一个对PropertyInfo的扩展方法

1
using System;<br>using System.Collections.Generic;<br>using System.Linq;<br>using System.Reflection;<br>using System.Web;<br><br>namespace AceepSystem.Models.Help<br>{<br>    public static class Virtual_Help<br>    {<br>      <br>        public static bool? IsVirtual(this PropertyInfo self)<br>        {<br>            if (self == null)<br>                throw new ArgumentNullException("self");<br><br>            bool? found = null;<br><br>            foreach (MethodInfo method in self.GetAccessors())<br>            {<br>                if (found.HasValue)<br>                {<br>                    if (found.Value != method.IsVirtual)<br>                        return null;<br>                }<br>                else<br>                {<br>                    found = method.IsVirtual;<br>                }<br>            }<br><br>            return found;<br>        }<br>       <br>    }<br>}

 使用方法如下

 string json = JsonConvert.SerializeObject(
               list,
                Formatting.Indented,
                JsonForEF.GetJsonConfig<dic_attribution>()
                );//转C#对象为Json数据

 

posted @   小小高  阅读(1162)  评论(2编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
历史上的今天:
2015-03-31 又看了半天的pdf格式的js方面的书,感觉受益匪浅啊,只会一点操作的我,要学好理论
2015-03-31 作为刚入职个把星期的小白,表示公司的项目就是复制粘贴,表示很迷茫,这样的话怎么成大牛哇?
点击右上角即可分享
微信分享提示