将实体框架对象序列化为 JSON
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/657939/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Serialize Entity Framework objects into JSON
提问by Program.X
It seems that serializing Entity Framework objects into JSON is not possible using either WCF's native DataContractJsonSerializer or ASP.NET's native JavaScript serializer. This is due to the reference counting issues both serializers reject. I have also tried Json.NET, which also fails specifically on a Reference Counting issue.
使用 WCF 的本机 DataContractJsonSerializer 或 ASP.NET 的本机 JavaScript 序列化程序似乎无法将 Entity Framework 对象序列化为 JSON。这是由于两个序列化程序都拒绝引用计数问题。我也试过Json.NET,它在引用计数问题上也特别失败。
Edit:Json.NET can now serialize and deserialize Entity Framework entities.
编辑:Json.NET 现在可以序列化和反序列化 Entity Framework 实体。
My objects are Entity Framework objects, which are overloaded to perform additional business functionality (eg. authentication, etc.) and I do not want to decorate these classes with platform-specific attributes, etc. as I want to present a platform-agnostic API.
我的对象是实体框架对象,它们被重载以执行额外的业务功能(例如身份验证等),我不想用特定于平台的属性等来装饰这些类,因为我想展示一个与平台无关的 API .
I've actually blogged about the individual steps I went though at https://blog.programx.co.uk/2009/03/18/wcf-json-serialization-woes-and-a-solution/
我实际上已经在博客上记录了我在https://blog.programx.co.uk/2009/03/18/wcf-json-serialization-woes-and-a-solution/ 上的各个步骤
Have I missed something obvious?
我错过了一些明显的东西吗?
回答by Craig Stuntz
The way I do this is by projecting the data I want to serialize into an anonymous type and serializing that. This ensures that only the information I actually want in the JSON is serialized, and I don't inadvertently serialize something further down the object graph. It looks like this:
我这样做的方法是将我想要序列化的数据投影为匿名类型并对其进行序列化。这确保只有我在 JSON 中真正想要的信息才会被序列化,并且我不会无意中序列化对象图更下方的某些内容。它看起来像这样:
var records = from entity in context.Entities
select new
{
Prop1 = entity.Prop1,
Prop2 = entity.Prop2,
ChildProp = entity.Child.Prop
}
return Json(records);
I find anonymous types just about ideal for this. The JSON, obviously, doesn't care what type was used to produce it. And anonymous types give you complete flexibility as to what properties and structure you put into the JSON.
我发现匿名类型非常适合于此。显然,JSON 并不关心用于生成它的类型。匿名类型使您可以完全灵活地将哪些属性和结构放入 JSON。
回答by John Saunders
Microsoft made an error in the way they made EF objects into data contracts. They included the base classes, and the back links.
Microsoft 在将 EF 对象转换为数据契约的方式上犯了一个错误。它们包括基类和反向链接。
Your best bet will be to create equivalent Data Transfer Object classes for each of the entities you want to return. These would include only the data, not the behavior, and not the EF-specific parts of an entity. You would also create methods to translate to and from your DTO classes.
最好的办法是为要返回的每个实体创建等效的数据传输对象类。这些将只包括数据,不包括行为,也不包括实体的特定于 EF 的部分。您还将创建与 DTO 类相互转换的方法。
Your services would then return the Data Transfer Objects.
然后,您的服务将返回数据传输对象。
回答by Anthony Main
My solution was to simply remove the parent reference on my child entities.
我的解决方案是简单地删除我的子实体上的父引用。
So in my model, I selected the relationship and changed the Parent reference to be Internal rather than Public.
所以在我的模型中,我选择了关系并将父引用更改为内部而不是公共。
May not be an ideal solution for all, but worked for me.
可能不是所有人的理想解决方案,但对我有用。
回答by Pat Migliaccio
Based off of @Craig Stuntz answer and similar to a DTO, for my solution I have created a partial class of the model (in a separate file) and a return object method with how I want it using only the properties that will be needed.
基于@Craig Stuntz 的回答并类似于 DTO,对于我的解决方案,我创建了模型的部分类(在单独的文件中)和返回对象方法,我希望它只使用需要的属性。
namespace TestApplication.Models
{
public partial class Employee
{
public object ToObject()
{
return new
{
EmployeeID = EmployeeID,
Name = Name,
Username = Username,
Office = Office,
PhoneNumber = PhoneNumber,
EmailAddress = EmailAddress,
Title = Title,
Department = Department,
Manager = Manager
};
}
}
}
And then I call it simply in my return:
然后我在返回时简单地调用它:
var employee = dbCtx.Employees.Where(x => x.Name == usersName).Single();
return employee.ToObject();
I think the accepted answer is more quick and easy, I just use my method to keep all of my returns consistent and DRY.
我认为接受的答案更快更容易,我只是用我的方法来保持我所有的回报一致和干燥。
回答by Anthony Main
FYI I found an alternative solution
仅供参考,我找到了一个替代解决方案
You can set the parent relationship as private so then the properties are not exposed during the translation removing the infinite property loop
您可以将父关系设置为私有,这样在删除无限属性循环的翻译过程中就不会公开属性
回答by Tebza
I battled with this problem for days,
我与这个问题斗争了好几天,
Solution. Inside your edmx window. - right click and add code generation item - Select Code tab - select EF 4x.POCOC Entity Generator
解决方案。在您的 edmx 窗口内。- 右键添加代码生成项 - 选择代码选项卡 - 选择 EF 4x.POCOC 实体生成器
If you don't see it, then you will have to install it with nuget, search EF.
如果你没有看到它,那么你必须用nuget安装它,搜索EF。
The Entity generator will generate all you complex type and entity object into simple classes to serialize into json.
实体生成器会将所有复杂类型和实体对象生成为简单类以序列化为 json。
回答by Tom
I solved it by getting only object types from System namespace, and then convert them to Dictionary and then add them to list. Works good for me :)
我通过只从 System 命名空间获取对象类型来解决它,然后将它们转换为 Dictionary 然后将它们添加到列表中。对我有用:)
It looks complicated, but this was the only generic solution that worked for me... I'm using this logic for a helper I'm making, so it's for a special use where I need to be able to intercept every object type in entity object, maybe someone could adapt it to his use.
它看起来很复杂,但这是唯一对我有用的通用解决方案......我正在将这个逻辑用于我正在制作的助手,所以它用于特殊用途,我需要能够拦截每个对象类型实体对象,也许有人可以适应他的使用。
List<Dictionary<string, string>> outputData = new List<Dictionary<string, string>>();
// convert all items to objects
var data = Data.ToArray().Cast<object>().ToArray();
// get info about objects; and get only those we need
// this will remove circular references and other stuff we don't need
PropertyInfo[] objInfos = data[0].GetType().GetProperties();
foreach (PropertyInfo info in objInfos) {
switch (info.PropertyType.Namespace)
{
// all types that are in "System" namespace should be OK
case "System":
propeties.Add(info.Name);
break;
}
}
Dictionary<string, string> rowsData = null;
foreach (object obj in data) {
rowsData = new Dictionary<string, string>();
Type objType = obj.GetType();
foreach (string propertyName in propeties)
{
//if You don't need to intercept every object type You could just call .ToString(), and remove other code
PropertyInfo info = objType.GetProperty(propertyName);
switch(info.PropertyType.FullName)
{
case "System.String":
var colData = info.GetValue(obj, null);
rowsData.Add(propertyName, colData != null ? colData.ToString() : String.Empty);
break;
//here You can add more variable types if you need so (like int and so on...)
}
}
outputData .Add(rowsData); // add a new row
}
"outputData " is safe for JSON encode... Hope someone will find this solution helpful. It was fun writing it :)
“outputData”对于 JSON 编码是安全的......希望有人会发现这个解决方案有帮助。写起来很有趣:)
回答by Mehal
One more solution if you want to have better code consistency is to use JavaScriptConverter which will handle circular reference dependencies and will not serialize such references.
如果您想获得更好的代码一致性,另一种解决方案是使用 JavaScriptConverter,它将处理循环引用依赖项并且不会序列化此类引用。
I've blogged about here:
我在这里写过博客:
http://hellowebapps.com/2010-09-26/producing-json-from-entity-framework-4-0-generated-classes/
http://hellowebapps.com/2010-09-26/production-json-from-entity-framework-4-0-generated-classes/

