How do I make JSON.NET ignore object relationships?

前端 未结 3 1507
被撕碎了的回忆
被撕碎了的回忆 2020-12-15 04:12

I\'m working on an Entity Framework project. I want to serialize a bunch of entity class instances. I\'ve bound these together into a container class:

public         


        
相关标签:
3条回答
  • 2020-12-15 04:57

    Also, if you are looking for a way to do this for all of your model classes with different member type names (for example, you have some models created by Entity Framework) this answer can help and you can ignore navigation properties in JSON serialization by it.

    0 讨论(0)
  • 2020-12-15 05:00

    An easier method is to modify your model T4 template (.tt) to append [JsonIgnore] attributes to your navigation properties, which will just leave the primitive types as serializable.

    0 讨论(0)
  • 2020-12-15 05:01

    First, to address your issues with reference loops-- The PreserveReferencesHandling setting controls whether Json.Net emits $id and $ref to track inter-object references. If you have this set to None and your object graph contains loops, then you will also need to set ReferenceLoopHandling to Ignore to prevent errors.

    Now, to get Json.Net to ignore all object references altogether and only serialize primitive properties (except in your Pseudocontext class of course), you do need a custom Contract Resolver, as you suggested. But don't worry, it is not as hard as you think. The resolver has the capability to inject a ShouldSerialize method for each property to control whether or not that property should be included in the output. So, all you need to do is derive your resolver from the default one, then override the CreateProperty method such that it sets ShouldSerialize appropriately. (You do not need a custom JsonConverter here, although it is possible to solve this problem with that approach. It would require quite a bit more code, however.)

    Here is the code for the resolver:

    class CustomResolver : DefaultContractResolver
    {
        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
        {
            JsonProperty prop = base.CreateProperty(member, memberSerialization);
    
            if (prop.DeclaringType != typeof(PseudoContext) && 
                prop.PropertyType.IsClass && 
                prop.PropertyType != typeof(string))
            {
                prop.ShouldSerialize = obj => false;
            }
    
            return prop;
        }
    }
    

    Here is a full demo showing the resolver in action.

    class Program
    {
        static void Main(string[] args)
        {
            // Set up some dummy data complete with reference loops
            Thing t1 = new Thing { Id = 1, Name = "Flim" };
            Thing t2 = new Thing { Id = 2, Name = "Flam" };
    
            Widget w1 = new Widget
            {
                Id = 5,
                Name = "Hammer",
                IsActive = true,
                Price = 13.99M,
                Created = new DateTime(2013, 12, 29, 8, 16, 3),
                Color = Color.Red,
            };
            w1.RelatedThings = new List<Thing> { t2 };
            t2.RelatedWidgets = new List<Widget> { w1 };
    
            Widget w2 = new Widget
            {
                Id = 6,
                Name = "Drill",
                IsActive = true,
                Price = 45.89M,
                Created = new DateTime(2014, 1, 22, 2, 29, 35),
                Color = Color.Blue,
            };
            w2.RelatedThings = new List<Thing> { t1 };
            t1.RelatedWidgets = new List<Widget> { w2 };
    
            // Here is the container class we wish to serialize
            PseudoContext pc = new PseudoContext
            {
                Things = new List<Thing> { t1, t2 },
                Widgets = new List<Widget> { w1, w2 }
            };
    
            // Serializer settings
            JsonSerializerSettings settings = new JsonSerializerSettings();
            settings.ContractResolver = new CustomResolver();
            settings.PreserveReferencesHandling = PreserveReferencesHandling.None;
            settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            settings.Formatting = Formatting.Indented;
    
            // Do the serialization and output to the console
            string json = JsonConvert.SerializeObject(pc, settings);
            Console.WriteLine(json);
        }
    
        class PseudoContext
        {
            public List<Thing> Things { get; set; }
            public List<Widget> Widgets { get; set; }
        }
    
        class Thing
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public List<Widget> RelatedWidgets { get; set; }
        }
    
        class Widget
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public bool IsActive { get; set; }
            public decimal Price { get; set; }
            public DateTime Created { get; set; }
            public Color Color { get; set; }
            public List<Thing> RelatedThings { get; set; }
        }
    
        enum Color { Red, White, Blue }
    }
    

    Output:

    {
      "Things": [
        {
          "Id": 1,
          "Name": "Flim"
        },
        {
          "Id": 2,
          "Name": "Flam"
        }
      ],
      "Widgets": [
        {
          "Id": 5,
          "Name": "Hammer",
          "IsActive": true,
          "Price": 13.99,
          "Created": "2013-12-29T08:16:03",
          "Color": 0
        },
        {
          "Id": 6,
          "Name": "Drill",
          "IsActive": true,
          "Price": 45.89,
          "Created": "2014-01-22T02:29:35",
          "Color": 2
        }
      ]
    }
    

    Hope this is in the ballpark of what you were looking for.

    0 讨论(0)
提交回复
热议问题