NewtonSoft add JSONIGNORE at runTime

后端 未结 5 2213
一个人的身影
一个人的身影 2020-11-27 05:05

Am looking to Serialize a list using NewtonSoft JSON and i need to ignore one of the property while Serializing and i got the below code

pub         


        
相关标签:
5条回答
  • 2020-11-27 05:22

    I think it would be best to use a custom IContractResolver to achieve this:

    public class DynamicContractResolver : DefaultContractResolver
    {
        private readonly string _propertyNameToExclude;
    
        public DynamicContractResolver(string propertyNameToExclude)
        {
            _propertyNameToExclude = propertyNameToExclude;
        }
    
        protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
        {
            IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
    
            // only serializer properties that are not named after the specified property.
            properties =
                properties.Where(p => string.Compare(p.PropertyName, _propertyNameToExclude, true) != 0).ToList();
    
            return properties;
        }
    }
    

    The LINQ may not be correct, I haven't had a chance to test this. You can then use it as follows:

    string json = JsonConvert.SerializeObject(car, Formatting.Indented,
       new JsonSerializerSettings { ContractResolver = new DynamicContractResolver("LastModified") });
    

    Refer to the documentation for more information.

    0 讨论(0)
  • 2020-11-27 05:30

    Based on @Underscore post above, I created a list of properties to exclude on serialization.

    public class DynamicContractResolver : DefaultContractResolver {
        private readonly string[] props;
    
        public DynamicContractResolver(params string[] prop) {
            this.props = prop;
        }
    
        protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) {
            IList<JsonProperty> retval = base.CreateProperties(type, memberSerialization);
    
            // retorna todas as propriedades que não estão na lista para ignorar
            retval = retval.Where(p => !this.props.Contains(p.PropertyName)).ToList();
    
            return retval;
        }
    }
    

    Use:

    string json = JsonConvert.SerializeObject(car, Formatting.Indented, 
        new JsonSerializerSettings { ContractResolver = new DynamicContractResolver("ID", "CreatedAt", "LastModified") });
    
    0 讨论(0)
  • 2020-11-27 05:39

    Try this:

        public static void IgnoreProperty<T, TR>(this T parameter, Expression<Func<T, TR>> propertyLambda)
        {
            var parameterType = parameter.GetType();
            var propertyName = propertyLambda.GetReturnedPropertyName();
            if (propertyName == null)
            {
                return;
            }
    
            var jsonPropertyAttribute = parameterType.GetProperty(propertyName).GetCustomAttribute<JsonPropertyAttribute>();
            jsonPropertyAttribute.DefaultValueHandling = DefaultValueHandling.Ignore;
        }
    
        public static string GetReturnedPropertyName<T, TR>(this Expression<Func<T, TR>> propertyLambda)
        {
            var member = propertyLambda.Body as MemberExpression;
            var memberPropertyInfo = member?.Member as PropertyInfo;
            return memberPropertyInfo?.Name;
        }
    

    So you can do this:

    carObject.IgnoreProperty(so => so.LastModified);
    
    0 讨论(0)
  • 2020-11-27 05:41

    With the reference Dynamically rename or ignore properties without changing the serialized class we can achieve JsonIgnore at run time. It's a workable solution.

    Consider Person Class for example:

    public class Person
    {
        // ignore property
        [JsonIgnore]
        public string Title { get; set; }
    
    // rename property
    [JsonProperty("firstName")]
    public string FirstName { get; set; }
    }
    

    Step 1: Create Class "PropertyRenameAndIgnoreSerializerContractResolver"

    public class PropertyRenameAndIgnoreSerializerContractResolver : DefaultContractResolver
    {
        private readonly Dictionary<Type, HashSet<string>> _ignores;
        private readonly Dictionary<Type, Dictionary<string, string>> _renames;
    
    public PropertyRenameAndIgnoreSerializerContractResolver()
    {
        _ignores = new Dictionary<Type, HashSet<string>>();
        _renames = new Dictionary<Type, Dictionary<string, string>>();
    }
    
    public void IgnoreProperty(Type type, params string[] jsonPropertyNames)
    {
        if (!_ignores.ContainsKey(type))
            _ignores[type] = new HashSet<string>();
    
        foreach (var prop in jsonPropertyNames)
            _ignores[type].Add(prop);
    }
    
    public void RenameProperty(Type type, string propertyName, string newJsonPropertyName)
    {
        if (!_renames.ContainsKey(type))
            _renames[type] = new Dictionary<string, string>();
    
        _renames[type][propertyName] = newJsonPropertyName;
    }
    
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
    
        if (IsIgnored(property.DeclaringType, property.PropertyName))
        {
            property.ShouldSerialize = i => false;
            property.Ignored = true;
        }
    
        if (IsRenamed(property.DeclaringType, property.PropertyName, out var newJsonPropertyName))
            property.PropertyName = newJsonPropertyName;
    
        return property;
    }
    
    private bool IsIgnored(Type type, string jsonPropertyName)
    {
        if (!_ignores.ContainsKey(type))
            return false;
    
        return _ignores[type].Contains(jsonPropertyName);
    }
    
    private bool IsRenamed(Type type, string jsonPropertyName, out string newJsonPropertyName)
    {
        Dictionary<string, string> renames;
    
        if (!_renames.TryGetValue(type, out renames) || !renames.TryGetValue(jsonPropertyName, out newJsonPropertyName))
        {
            newJsonPropertyName = null;
            return false;
        }
    
        return true;
    }
    }
    

    Step 2: Add code in your method where Jsonignore want to apply

    var person = new Person();
    var jsonResolver = new PropertyRenameAndIgnoreSerializerContractResolver();
    
    jsonResolver.IgnoreProperty(typeof(Person), "Title");
    jsonResolver.RenameProperty(typeof(Person), "FirstName", "firstName");
    
    var serializerSettings = new JsonSerializerSettings();
    serializerSettings.ContractResolver = jsonResolver;
    
    var json = JsonConvert.SerializeObject(person, serializerSettings);
    
    0 讨论(0)
  • 2020-11-27 05:45

    No need to do the complicated stuff explained in the other answer.

    NewtonSoft JSON has a built-in feature for that:

    public bool ShouldSerializeINSERT_YOUR_PROPERTY_NAME_HERE()
    {
        if(someCondition){
            return true;
        }else{
            return false;
        }
    }
    

    It is called "conditional property serialization" and the documentation can be found here.

    Warning: first of all, it is important to get rid of [JsonIgnore] above your {get;set;} property. Otherwise it will overwrite the ShouldSerializeXYZ behavior.

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