Entity framework serialize POCO to JSON

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace Web.Common
{
    /// <summary>
    /// 都是无法序列化JSON序列化 EF的实体对象,
    /// 要么就必须声明什么DataMember??,需要删除实体类的IsRefrence
    /// 太恶心了,网路上找到一个,自己汉化了一下。
    /// </summary>
    public static class JsonHelper
    {
        /// <summary>
        /// 将对象转化为Json字符串
        /// </summary>
        /// <typeparam name="T">源类型</typeparam>
        /// <param name="instance">源类型实例</param>
        /// <returns>Json字符串</returns>
        public static string ToJson(this object obj)
        {
            //string jsonText = JsonConvert.SerializeObject(obj);
            //return jsonText;

            return JsonHelper.JsonSerialize(obj);
        }

        public static string JsonSerialize<T>(T obj) where T : class
        {
            var sb = new StringBuilder("{");

            var parentType = obj.GetType(); // I get type from given object 

            //使用反射来检索该类型的所有属性
            var ms = parentType.GetMembers().Where(v => v.MemberType
                == MemberTypes.Property).ToList<MemberInfo>();

            const string doubleQuote = "\"";
            var counter = 0;
            var stringTypes = new List<String> { "String", "Guid", 
            "Boolean" };

            ///以下类型的使用实体框架。定义忽略的数据类型
            var ignoreEntityTypes = new List<String> { "EntityReference`1", 
            "EntityCollection`1", "EntityState", 
            "EntityKey", "EntitySetName" };

            //开始迭代查找每个属性
            foreach (PropertyInfo p in ms)
            {
                counter++;
                var propertyName = p.Name;
                var propertyType = p.PropertyType;
                var propertyValue = p.GetValue(obj, null);

                //如果属性类型匹配 ignoreTypes,那么进入下一个循环。
                if (ignoreEntityTypes.Contains(propertyType.Name))
                {
                    continue;
                }

                if (stringTypes.Contains(propertyType.Name))
                {
                    if (propertyValue == null)
                    {
                        sb.Append(doubleQuote + propertyName + doubleQuote +
                                  ":" + "null");
                    }

                    else
                    {
                        sb.Append(doubleQuote + propertyName + doubleQuote +
                            ":" + doubleQuote + propertyValue.ToString() + doubleQuote);
                    }
                }

                else if (propertyType != null && propertyType.IsPrimitive)
                {
                    sb.Append(doubleQuote + propertyName + doubleQuote
                        + ":" + propertyValue.ToString());
                }

                //我仍然有疑问如何处理日期和时间,处理日期属性
                else if (propertyType.Name == "DateTime")
                {
                    var dt = (DateTime)propertyValue;
                    sb.Append(doubleQuote + propertyName
                        + doubleQuote + ":"
                        + "new Date(" + dt.Ticks.ToString() + ")");
                }
                else
                {
                    if (propertyValue != null)
                    {
                        sb.Append(doubleQuote + propertyType.Name + doubleQuote + ":");
                        //如果属性值是另一个实体,然后
                        //递归调用的方法。
                        sb.Append(JsonSerialize(propertyValue));
                    }
                    else
                    {
                        continue;
                    }
                }
                //如果不是最后一个属性,然后添加逗号
                if (counter < ms.Count)
                {
                    sb.Append(",");
                }
            }
            sb.Append("}");
            var result = sb.ToString().Replace(",}", "}");
            return result;

        }
    }
}


http://geeks.ms/blogs/fernandezja/archive/2010/05/13/entity-framework-serializar-entidades-con-json-net-error-the-type-entidadxxx-cannot-be-serialized-to-json-because-its-isreference-setting-is-true.aspx


m using Ef 4.1 and I've got a POCO object I'd like to serialize to JSON, I've read there is a problem to do so when using lazy loading but I'm not sure I can because a Message can have a collection ofMessage.

Is there any way to do this? sirialize this kind of object into JSON?

My Message object looks like:

public class Message
{
    [Key]
    public int Id { get; set; }
    public int? ParentId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public DateTime CreatedAt { get; set; }
    public DateTime? LastModified { get; set; }

    public virtual User User { get; set; }

    public virtual Message Parent { get; set; }

    public virtual ICollection<Message> Children { get; set; }
}
link | improve this question

 
feedback

3 Answers

up vote 2 down vote accepted

The problem is circular references. An easy way to avoid this is to use Json.Nethttp://james.newtonking.com/projects/json-net.aspx instead of the default MVC json serializer. The latest version of Json.Net will serialize objects with circular references out of the box.http://james.newtonking.com/projects/json/help/PreserveObjectReferences.html for more info on the problem

link | improve this answer
 
Thanks! ReferenceLoopHandling.Ignore and a custom ContractResolver did the trick :-) –  CD..  Aug 30 '11 at 6:35
feedback

Eager load it using Include(). Sample linq:

var serializeMe = (from m in MyContext.Message.Include("User") where m.Id == someValue select m).ToList();

That will tell EF to load the User navigation property right away instead of lazy loading it, and the serializer should have no problem with it then.

link | improve this answer
 
Including the related entity solved a problem I was having serializing an EF object graph because I was able to take the virtual keyword off of the offending property in my class. Thanks! –  marc  Feb 15 at 16:48
feedback

How about this:

  • Mark your class as [Serializable]
  • Use the JsonSerializer to serialize your object to JSON.
  • Perhaps use eager loading on the properties in your EF query?
Message msg = new Message();
var serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(msg.GetType());
MemoryStream ms = new MemoryStream();
serializer.WriteObject(ms, msg);
string json = Encoding.Default.GetString(ms.ToArray());


[Serializable]
public class Message
{
}
link | improve this answer
 
thanks for the detailed answer, but I'm afraid the virtual properties are not loaded this way... –  CD..  Aug 29 '11 at 20:51
 
@CD : what am I missing? The virtual property serialized just fine for the collection and the single properties: i.imgur.com/9mkW3.png –  p.campbell  Aug 29 '11 at 21:03
 
In EF any virtual ICollection will be lazy-loaded.. –  CD..  Aug 29 '11 at 21:08
Was this post useful to you?      



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值