Can I optionally turn off the JsonIgnore attribute at runtime?

后端 未结 3 867
一生所求
一生所求 2020-11-29 05:41

I am creating a JSON file with Newtonsoft.Json from a set of classes. The file created is very large, so I have created JsonProperty\'s for the properties to re

相关标签:
3条回答
  • 2020-11-29 06:19

    Json support us to ignore property that don't want return. Example

    class Foo
    {
        public int Id { get; set; }
        public string Name { get; set; }
        [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public string AlternateName { get; set; }    
    }
    

    How to use it:

    Foo foo = new Foo
    {
        Id = 1,
        Name = "Thing 1",
        AlternateName = null,   
    };
    
    string json = JsonConvert.SerializeObject(foo);
    
    0 讨论(0)
  • 2020-11-29 06:27

    Yes, this can be done using a custom ContractResolver.

    You didn't show any code, so I'll just make up an example. Let's say I have a class Foo as shown below. I want the Id and Name properties in the serialization output, but I'm definitely not interested in the AlternateName and Color. I've marked those with [JsonIgnore]. I want the description to appear, but sometimes this can get really long, so I've used a custom JsonConverter to limit its length. I also want to use a shorter property name for the description, so I've marked it with [JsonProperty("Desc")].

    class Foo
    {
        public int Id { get; set; }
        public string Name { get; set; }
        [JsonIgnore]
        public string AlternateName { get; set; }
        [JsonProperty("Desc")]
        [JsonConverter(typeof(StringTruncatingConverter))]
        public string Description { get; set; }
        [JsonIgnore]
        public string Color { get; set; }
    }
    

    When I serialize an instance of the above...

    Foo foo = new Foo
    {
        Id = 1,
        Name = "Thing 1",
        AlternateName = "The First Thing",
        Description = "This is some lengthy text describing Thing 1 which you'll no doubt find very interesting and useful.",
        Color = "Yellow"
    };
    
    string json = JsonConvert.SerializeObject(foo, Formatting.Indented);
    

    ...I get this output:

    {
      "Id": 1,
      "Name": "Thing 1",
      "Desc": "This is some lengthy text describing Thing 1 "
    }
    

    Now, let's say that I sometimes want to get the full JSON output, ignoring my customizations. I can use a custom ContractResolver to programmatically "unapply" the attributes from the class. Here's the code for the resolver:

    class IgnoreJsonAttributesResolver : DefaultContractResolver
    {
        protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
        {
            IList<JsonProperty> props = base.CreateProperties(type, memberSerialization);
            foreach (var prop in props)
            {
                prop.Ignored = false;   // Ignore [JsonIgnore]
                prop.Converter = null;  // Ignore [JsonConverter]
                prop.PropertyName = prop.UnderlyingName;  // restore original property name
            }
            return props;
        }
    }
    

    To use the resolver, I add it to the JsonSerializerSettings and pass the settings to the serializer like this:

    JsonSerializerSettings settings = new JsonSerializerSettings();
    settings.ContractResolver = new IgnoreJsonAttributesResolver();
    settings.Formatting = Formatting.Indented;
    
    string json = JsonConvert.SerializeObject(foo, settings);
    

    The output now includes the ignored properties, and the description is no longer truncated:

    {
      "Id": 1,
      "Name": "Thing 1",
      "AlternateName": "The First Thing",
      "Description": "This is some lengthy text describing Thing 1 which you'll no doubt find very interesting and useful.",
      "Color": "Yellow"
    }
    

    Full demo here: https://dotnetfiddle.net/WZpeWt

    0 讨论(0)
  • 2020-11-29 06:37

    If you are willing to use F# (or simply use an API not optimized for C#), the FSharp.JsonSkippable library contains a generic wrapper type that allows you to control in a simple and strongly typed manner whether to include a given property when serializing (and determine whether a property was included when deserializing), and moreover, to control/determine exclusion separately of nullability. (Full disclosure: I'm the author of the library.)

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