How do I make JSON.NET ignore object relationships?

前端 未结 3 1510
被撕碎了的回忆
被撕碎了的回忆 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 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 { t2 };
            t2.RelatedWidgets = new List { 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 { t1 };
            t1.RelatedWidgets = new List { w2 };
    
            // Here is the container class we wish to serialize
            PseudoContext pc = new PseudoContext
            {
                Things = new List { t1, t2 },
                Widgets = new List { 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 Things { get; set; }
            public List Widgets { get; set; }
        }
    
        class Thing
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public List 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 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.

提交回复
热议问题