Сериализация объектов Entity Framework в JSON - PullRequest
44 голосов
/ 18 марта 2009

Кажется, что сериализация объектов Entity Framework в JSON невозможна с использованием собственного DataContractJsonSerializer WCF или собственного сериализатора JavaScript ASP.NET. Это связано с проблемами подсчета ссылок, которые отвергают оба сериализатора. Я также попытался Json.NET , что также не работает именно из-за проблемы подсчета ссылок.


Редактировать: Json.NET теперь может сериализовать и десериализовать сущности Entity Framework .


Мои объекты являются объектами Entity Framework, которые перегружены для выполнения дополнительных бизнес-функций (например, аутентификация и т. Д.), И я не хочу украшать эти классы атрибутами, специфичными для платформы, и т. Д., Поскольку я хочу представить платформу -агностический API.

На самом деле я писал в блоге об отдельных шагах, которые я прошел, по адресу https://blog.programx.co.uk/2009/03/18/wcf-json-serialization-woes-and-a-solution/

Я что-то упустил очевидное?

Ответы [ 8 ]

72 голосов
/ 18 марта 2009

Я делаю это, проецируя данные, которые я хочу сериализовать, в анонимный тип и сериализуя их. Это гарантирует, что сериализуется только та информация, которую я на самом деле хочу получить в JSON, и я не могу случайно сериализовать что-то еще вниз по графу объектов. Это выглядит так:

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

Я нахожу анонимные типы почти идеальными для этого. JSON, очевидно, не волнует, какой тип использовался для его создания. А анонимные типы дают вам полную гибкость в отношении того, какие свойства и структуру вы помещаете в JSON.

16 голосов
/ 18 марта 2009

Microsoft допустила ошибку в том, что они превратили объекты EF в контракты данных. Они включали базовые классы и обратные ссылки.

Лучше всего будет создать эквивалентные классы объектов передачи данных для каждой сущности, которую вы хотите вернуть. Они будут включать только данные, а не поведение и не специфичные для EF части объекта. Вы также создадите методы для перевода в и из ваших классов DTO.

Тогда ваши службы вернут объекты передачи данных.

2 голосов
/ 10 мая 2016

Основываясь на ответе @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
            };
        }
    }
}

А потом я называю это просто в ответ:

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

Я думаю, что принятый ответ является более быстрым и легким, я просто использую свой метод, чтобы все мои результаты были согласованными и сухими.

2 голосов
/ 23 февраля 2012

Моим решением было просто удалить родительскую ссылку на мои дочерние объекты.

Таким образом, в моей модели я выбрал отношение и изменил ссылку Родитель на Внутренний, а не Открытый.

Может быть не идеальным решением для всех, но сработало для меня.

1 голос
/ 03 января 2014

Я решил это, получив только типы объектов из пространства имен System, затем преобразовал их в словарь и затем добавил их в список. Работает хорошо для меня:)

Это выглядит сложно, но это было единственное общее решение, которое сработало для меня ... Я использую эту логику для помощника, которого я создаю, поэтому он предназначен для специального использования, где мне нужно иметь возможность перехватывать каждый тип объекта в объекте сущности, может быть, кто-то может адаптировать его к его использованию.

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» безопасен для кодирования JSON ... Надеюсь, кто-то найдет это решение полезным. Было весело писать это:)

1 голос
/ 24 июля 2012

Я боролся с этой проблемой в течение нескольких дней,

Решение. Внутри вашего окна EDMX. - щелкните правой кнопкой мыши и добавьте элемент генерации кода - Выберите вкладку Код - выберите EF 4x.POCOC Entity Generator

Если вы его не видите, вам придется установить его с помощью Nuget, поиск EF.

Генератор сущностей сгенерирует весь сложный тип и объект сущности в простые классы для сериализации в json.

1 голос
/ 28 мая 2012

К вашему сведению я нашел альтернативное решение

Вы можете установить родительские отношения как частные, чтобы свойства не отображались во время перевода, удаляя бесконечный цикл свойств

1 голос
/ 26 сентября 2010

Еще одно решение, если вы хотите улучшить согласованность кода, - это использовать JavaScriptConverter, который будет обрабатывать зависимости циклических ссылок и не будет сериализовывать такие ссылки.

Я писал здесь:

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

...