Can I optionally turn off the JsonIgnore attribute at runtime?
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
Ignore [JsonIgnore] Attribute on Serialization / Deserialization
You were on the right track, you only missed the property.Ignored
serialization option.
Change your contract to the following
public class JsonIgnoreAttributeIgnorerContractResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
property.Ignored = false; // Here is the magic
return property;
}
}
NewtonSoft add JSONIGNORE at runTime
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.
Newtonsoft ignore attributes?
I ended up making all properties I needed to only add attributes to virtual, and overriding them alone in another class, with the relevant newtonsoft attributes.
This allows me to have different serialisation behavior when de-serialising from CouchDB and serialising for a GET, without too much dupe. It is fine, and a bonus, that the two are coupled; any changes in the base i would want anyway.
It would still be nice to know if my original question is possible?
JsonIgnore attribute conditional analog but not ShouldSerialize
This is an interesting problem. My answer borrows heavily from the link you provided, but checks for a custom attribute defining your "Premium Content" (things that the user paid for):
Like your link, I have defined a class Foo
, which will be serialized. It contains a child object PremiumStuff
, which contains things that should only be serialized if the user paid for them. I have marked this child object with a custom attribute PremiumContent
, which is also defined in this code snippet. I then used a custom class that inherits from DefaultContractResolver
just like the link did, but in this implementation, I am checking each property for our custom attribute, and running the code in the if
block only if the property is marked as PremiumContent
. This conditional code checks a static bool called AllowPremiumContent
to see whether we are allowing the premium content to be serialized. If it is not allowed, then we are setting the Ignore
flag to true:
class Foo
{
public int Id { get; set; }
public string Name { get; set; }
[JsonIgnore]
public string AlternateName { get; set; }
[PremiumContent]
public PremiumStuff ExtraContent { get; set; }
}
class PremiumStuff
{
public string ExtraInfo { get; set; }
public string SecretInfo { get; set; }
}
class IncludePremiumContentAttributesResolver : DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
IList<JsonProperty> props = base.CreateProperties(type, memberSerialization);
foreach (var prop in props)
{
if (Attribute.IsDefined(type.GetProperty(prop.PropertyName), typeof(PremiumContent)))
{
//if the attribute is marked with [PremiumContent]
if (PremiumContentRights.AllowPremiumContent == false)
{
prop.Ignored = true; // Ignore this if PremiumContentRights.AllowPremiumContent is set to false
}
}
}
return props;
}
}
[System.AttributeUsage(System.AttributeTargets.All)]
public class PremiumContent : Attribute
{
}
public static class PremiumContentRights
{
public static bool AllowPremiumContent = true;
}
Now, let's implement this and see what we get. Here is my test code:
PremiumContentRights.AllowPremiumContent = true;
Foo foo = new Foo()
{
Id = 1,
Name = "Hello",
AlternateName = "World",
ExtraContent = new PremiumStuff()
{
ExtraInfo = "For premium",
SecretInfo = "users only."
}
};
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.ContractResolver = new IncludePremiumContentAttributesResolver();
settings.Formatting = Formatting.Indented;
string json = JsonConvert.SerializeObject(foo, settings);
Debug.WriteLine(json);
In the first line, PremiumContentRights.AllowPremiumContent
is set to true, and here is the output:
{
"Id": 1,
"Name": "Hello",
"ExtraContent": {
"ExtraInfo": "For premium",
"SecretInfo": "users only."
}
}
If we set AllowPremiumContent
to False
and run the code again, here is the output:
{
"Id": 1,
"Name": "Hello"
}
As you can see, the ExtraContent
property is included or ignored depending on the state of the AllowPremiumContent
variable.
Is it possible to JSON Serialize a property marked as [Ignore] automatically
I guess one way to do this is add the ignored fields back:
JsonConvert.DeserializeObject<Contact>(clone).Name=contact.Name
But the point of using ignore is so that it doesn't get serialized.
Another option is to specify a custom contract resolver in jsonserializersettings:
var deserializeSettings = new JsonSerializerSettings
{
ObjectCreationHandling = ObjectCreationHandling.Replace,
ContractResolver = new DynamicContractResolver()
};
https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Serialization_IContractResolver.htm
public class DynamicContractResolver: DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
//property.HasMemberAttribute = true;
property.Ignored = false;
//property.ShouldSerialize = instance =>
//{
// return true;
//};
return property;
}
}
control [JsonIgnore] in ASP.NET Web API during runtime
I know two way to solve this problem:
- You may add additional boolean property (with specific name) into your model. This is solution is very simple, but requires changes to your model.
- You may write own
IContractResolver
. This method is more complex, but more flexible.
Both solutions described here: 'Conditional Property Serialization' http://james.newtonking.com/json/help/index.html?topic=html/ConditionalProperties.htm
Dynamically ignore the properties on class using json.net
Json.NET has the ability to conditionally serialize properties by placing a ShouldSerialize method on a class.
the following link will give details
http://www.newtonsoft.com/json/help/html/conditionalproperties.htm
Related Topics
Custom Authentication in ASP.NET-Core
How to Convert an Expression Tree to a Partial SQL Query
Why Use Httpclient for Synchronous Connection
Using Razor Outside of MVC in .Net Core
How to Use Push Notifications in Xamarin Forms
Startup.Cs in a Self-Hosted .Net Core Console Application
C# VS C - Big Performance Difference
How to Force C# .Net App to Run Only One Instance in Windows
How to Use a Client Certificate to Authenticate and Authorize in a Web API
How to Redirect from Onactionexecuting in Base Controller
How to Download a Nuget Package Without Nuget.Exe or Visual Studio Extension
Differencebetween Ienumerator and Ienumerable
Apply Function to All Elements of Collection Through Linq
Visual Studio 2015 Broken Razor Intellisense
Get User Location by Ip Address
Difference Between System.Datetime.Now and System.Datetime.Today