Serializar objetos de Entity Framework en JSON

Parece que la serialización de objetos de Entity Framework en JSON no es posible utilizando el DataContractJsonSerializer nativo de WCF o el serializador de JavaScript nativo de ASP.NET. Esto se debe a los problemas de conteo de referencias que rechazan ambos serializadores. También probé Json.NET , que también falla específicamente en un problema de recuento de referencias.


Editar: Json.NET ahora puede serializar y deserializar las entidades de Entity Framework .


Mis objetos son objetos de Entity Framework, que están sobrecargados para realizar funciones comerciales adicionales (por ejemplo, autenticación, etc.) y no quiero decorar estas clases con atributos específicos de plataforma, etc. ya que quiero presentar una API independiente de la plataforma .

De hecho, publiqué en mi blog los pasos individuales que realicé en https://blog.programx.co.uk/2009/03/18/wcfjson-serialization-woes-and-a-solution/

¿Me he perdido algo obvio?

La forma en que lo hago es proyectando los datos que deseo serializar en un tipo anónimo y serializando eso. Esto asegura que solo la información que realmente quiero en el JSON está serializada, y no serializo inadvertidamente algo más abajo en el gráfico del objeto. Se parece a esto:

var records = from entity in context.Entities select new { Prop1 = entity.Prop1, Prop2 = entity.Prop2, ChildProp = entity.Child.Prop } return Json(records); 

Encuentro tipos anónimos casi ideales para esto. El JSON, obviamente, no importa qué tipo se usó para producirlo. Y los tipos anónimos le brindan flexibilidad completa en cuanto a qué propiedades y estructura pone en el JSON.

Microsoft cometió un error en la forma en que convirtieron los objetos EF en contratos de datos. Incluyeron las clases base y los enlaces de atrás.

Su mejor opción será crear clases de objetos de transferencia de datos equivalentes para cada una de las entidades que desee devolver. Estos incluirían solo los datos, no el comportamiento, y no las partes específicas de EF de una entidad. También crearía métodos para traducir hacia y desde sus clases de DTO.

Sus servicios devolverían los objetos de transferencia de datos.

Mi solución fue simplemente eliminar la referencia principal en las entidades de mi hijo.

Entonces, en mi modelo, seleccioné la relación y cambié la referencia principal para que sea interna en lugar de pública.

Puede que no sea una solución ideal para todos, pero funcionó para mí.

Basado en la respuesta de @Craig Stuntz y similar a un DTO, para mi solución he creado una clase parcial del modelo (en un archivo separado) y un método de objeto de retorno con la forma en que lo deseo usando solo las propiedades que serán necesarias.

 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 }; } } } 

Y luego lo llamo simplemente en mi regreso:

 var employee = dbCtx.Employees.Where(x => x.Name == usersName).Single(); return employee.ToObject(); 

Creo que la respuesta aceptada es más rápida y fácil, solo uso mi método para mantener todas mis devoluciones consistentes y SECAS.

Una solución más si desea tener una mejor consistencia del código es usar JavaScriptConverter, que manejará las dependencias de referencia circulares y no serializará dichas referencias.

He blogueado aquí:

http://hellowebapps.com/2010-09-26/producing-json-from-entity-framework-4-0-generated-classes/

FYI encontré una solución alternativa

Puede establecer la relación principal como privada para que las propiedades no se expongan durante la traducción, eliminando el bucle infinito de propiedad

Luché con este problema por días,

Solución. Dentro de tu ventana de edmx – haga clic con el botón derecho y agregue el elemento de generación de código – Seleccione la pestaña Código – seleccione EF 4x.POCOC Entity Generator

Si no lo ves, entonces tendrás que instalarlo con Nuget, buscar EF.

El generador de entidades generará todo tipo de objeto complejo y objeto de entidad en clases simples para serializar en json.

Lo resolví obteniendo solo tipos de objetos del espacio de nombres del Sistema, y ​​luego los convertí a Diccionario y luego los agregué a la lista. Funciona bien para mí 🙂

Parece complicado, pero esta fue la única solución genérica que funcionó para mí … Estoy usando esta lógica para un asistente que estoy creando, por lo que es para un uso especial donde necesito poder interceptar cada tipo de objeto en objeto de entidad, tal vez alguien podría adaptarlo a su uso.

 List> outputData = new List>(); // convert all items to objects var data = Data.ToArray().Cast().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 rowsData = null; foreach (object obj in data) { rowsData = new Dictionary(); 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” es seguro para la encoding JSON … Espero que alguien encuentre útil esta solución. Fue divertido escribirlo 🙂