I have a class set up as follows:
public class Foo
{
public string string1 { get; set; }
public string string2 { get; set; }
public string string3
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();
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.
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.
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"));
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.
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 };