JSON.Net Ignore Property during deserialization

前端 未结 6 615
别跟我提以往
别跟我提以往 2020-12-29 19:55

I have a class set up as follows:

public class Foo
{
    public string string1 { get; set; }
    public string string2 { get; set; }
    public string string3         


        
相关标签:
6条回答
  • 2020-12-29 20:25

    Here's the Newtonsoft Json preferred way to ignore a property without having to modify the class as based on http://james.newtonking.com/json/help/index.html?topic=html/ReducingSerializedJSONSize.htm

    This one is used to ignore lazy reference properties of EF or Linq2Sql

    public class DynamicContractResolver : DefaultContractResolver
    {
        protected override IList<JsonProperty> CreateProperties(Type type, 
            MemberSerialization memberSerialization)
        {
            Func<Type,bool> includeProperty = t => t.IsValueType || t.Namespace.StartsWith("System") && t.Namespace.StartsWith("System.Data")==false; 
            IList<JsonProperty> properties = base.CreateProperties(type, memberSerialization);
            var allProperties = properties.Select (p => new{p.PropertyName,Including=includeProperty(p.PropertyType), p.PropertyType});//.Dump("props");
            var warnProperties=allProperties.Where (a =>a.Including && a.PropertyType.IsValueType==false && a.PropertyType.Name.IsIgnoreCaseMatch("String")==false) ;
    
            //linq pad debugging helper
            //var propertyTypesSerializing= allProperties.Where (p => p.Including).Select (p => p.PropertyType).Distinct().OrderBy (p => p.Name).Dump();
    
            if(warnProperties.Any())
            {
                //LinqPad helper
                //Util.Highlight(warnProperties.ToArray()).Dump("warning flag raised, aborting");
                throw new ArgumentOutOfRangeException();
            }
    
            properties = properties.Where(p =>includeProperty(p.PropertyType)).ToList();
            return properties;
        }
    }
    

    All the .Dump() calls are just linqpad debugging helpers, not needed method calls.

    sample usage:

    var inactives = from am in Aspnet_Memberships
            join mm in Member_members on am.UserId equals mm.Member_guid
            where mm.Is_active==false && mm.Org_id==1
            select new{am,mm};
            //inactives.Take(4).ToArray().Dump();
            var serialized = JsonConvert.SerializeObject(
                inactives.Skip(1).Select(i => i.mm).First(), 
                new  JsonSerializerSettings()
                {
                    ContractResolver = new DynamicContractResolver(), 
                    PreserveReferencesHandling = PreserveReferencesHandling.None,
                    ReferenceLoopHandling= ReferenceLoopHandling.Ignore
                }); 
                //.Dump();
    
    0 讨论(0)
  • 2020-12-29 20:38

    This is a lame workaround but you could make a method to manually load the json. If it's too much data to load without an automatic deserializer just remove the nodes that you don't want. This is a lot slower though.

    public static List<Foo> FromJson(string input) {
        var json = JToken.Parse(input);
        json["key"].Remove();
        var foo = JsonConvert.DeserializeObject<List<Foo>>(json.ToString());
    
    }
    

    This is an interesting problem I wonder if anyone has a better solution for it.

    0 讨论(0)
  • 2020-12-29 20:39

    You can use MissingMemberHandling property of the JsonSerializerSettings object.

    Example usage:

    var jsonSerializerSettings = new JsonSerializerSettings();
    jsonSerializerSettings.MissingMemberHandling = MissingMemberHandling.Ignore;
    
    JsonConvert.DeserializeObject<YourClass>(jsonResponse, jsonSerializerSettings);
    

    More info here.

    0 讨论(0)
  • 2020-12-29 20:42

    Alternative;

    If ResponseAttribute has in model or string parameters

    public class ResponseAttribute : Attribute { }
    
    public class ModelItem
    {
        [Response]
        public Guid Id { get; set; }
    }
    

    Code;

    public class CustomJsonSerializer : JsonSerializerSettings
    {
        public CustomJsonSerializer()
        {
            ContractResolver = new CustomContractResolver();
        }
    
        public CustomJsonSerializer(params string[] members)
        {
            ContractResolver = new CustomContractResolver(members);
        }
    
        public class CustomContractResolver : DefaultContractResolver
        {
            public string[] Members { get; set; }
            public CustomContractResolver(params string[] _members)
            {
                Members = _members;
            }
    
            protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
            {
                JsonProperty property = base.CreateProperty(member, memberSerialization);
    
                if (Members?.Length > 0)
                    property.ShouldSerialize = instance => { return Members.Contains(member.Name); };
                else
                    property.ShouldSerialize = instance => { return member.GetCustomAttribute<ResponseAttribute>() != null; };
    
                return property;
            }
        }
    }
    

    Use;

    return new JsonResult(model, new CustomJsonSerializer());
    

    or

    return new JsonResult(model, new CustomJsonSerializer("Id","Test","Test2"));
    
    0 讨论(0)
  • 2020-12-29 20:46

    Adding to drzaus answer: You can use the DefaultContractResolver he suggested .. just in its CreateProperty use property.Ignored = true; instead of property.ShouldSerialize, then its good either when you pass the JsonSerializerSettings to the DeserializeObject function or the SerializeObject function.

    0 讨论(0)
  • 2020-12-29 20:48

    Similar to @Maslow's solution, you can use another general purpose "ignorer":

    var jsonResolver = new IgnorableSerializerContractResolver();
    // ignore your specific property
    jsonResolver.Ignore(typeof(Foo), "string2");
    // ignore single datatype
    jsonResolver.Ignore(typeof(System.Data.Objects.DataClasses.EntityObject));
    var jsonSettings = new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, ContractResolver = jsonResolver };
    
    0 讨论(0)
提交回复
热议问题