Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serialize one to many relationships in Json.net

I am using the Entity Framework code first for data access and I have a Company class which has a collection of Employees. The Employee class also has a Company property.

I would like to be able to serialize a Company and include the list of employees in the serialization.

Here is Company:

public class Company
{
public long Id { get; set; }
public string Name { get; set; }
public DateTime? Established { get; set; }

public virtual IList<Employee> Employees { get; set; }

public DateTime? DateCreated { get; set; }
public DateTime? DateUpdated { get; set; }
}

Here is Employee

public class Employee
{
public long Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }

public virtual Company Company { get; set; }

public DateTime? DateCreated { get; set; }
public DateTime? DateUpdated { get; set; }
}

I get a serialization Exception "Self referencing loop detected for type" when I try to serialize a Company object.

Thanks.

like image 697
Emad Avatar asked Apr 24 '11 07:04

Emad


3 Answers

I think they have fixed this in the latest version.

Check out the help docs under the section "Serializing and Deserializing JSON -> Serialization and Preserving Object References".

Set this setting when initializing the JSON.Net Serializer:

PreserveReferencesHandling = PreserveReferencesHandling.Objects;

So an example would be this:

var serializerSettings = new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects };

string json = JsonConvert.SerializeObject(people, Formatting.Indented, serializerSettings);

I verified that this works with my code first solution, and a circular reference in the navigation properties. If you look at the resulting JSON it should have "$id" and "$ref" properties everywhere.

like image 72
John B Avatar answered Nov 01 '22 18:11

John B


Updated Answer

You can either:

  • reconfigure json.net to ignore selfreference loops
  • use the [JsonIgnore] Attribute
  • use a custom converter that remove the navigation in the child
  • or you can use Data Transfer Objects
like image 6
sra Avatar answered Nov 01 '22 19:11

sra


In case this helps anyone, I thought I'd document how we resolved this same error for our purposes when using Entity Framework 4.3.1 and JSON.Net 4.5.3.

We are using the Database First DbContext approach. For our needs, we could resolve it using the [JsonIgnore] attribute. The trick is just that since changes to the automatically generated entity classes are overwritten when you refresh from the database, with Database First you can add the attributes using the "metadata buddy class" approach given in this StackOverflow post.

Below is a code excerpt. We had a "Query" object (class Query) that had relationships to "Company" and "User" objects. In a new class file, we declare the partial class with a [MetadataType] attribute, and then in the QueryMetadata class we specified, we annotate the members we want to ignore— namely the public virtual members that EF4.x adds to express the relationships (a.k.a. navigation properties).

The Query entity also has foreign key fields (named FK_User and FK_Company in our case). These fields do not need the [JsonIgnore] attribute— they can be serialized with their foreign key values.

[MetadataType(typeof(QueryMetadata))]
public partial class Query
{
}


public class QueryMetadata
{
    [JsonIgnore]
    public virtual Company company { get; set; }
    [JsonIgnore]
    public virtual User user { get; set; }
}

However, if we actually had to also serialize the related Company or User objects, we'd hit a brick wall! The approach suggested by John Bubriski here wouldn't work for us since we want to rely on Entity Framework change tracking.

like image 6
Martin_W Avatar answered Nov 01 '22 19:11

Martin_W