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 ; }
}
asked
Aug 29 '11 at 20:35
100% accept rate
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.
answered
Aug 29 '11 at 21:00
feedback
ReferenceLoopHandling.Ignore
and a customContractResolver
did the trick :-) – CD.. Aug 30 '11 at 6:35