I have a DTO class which I Serialize
Json.Serialize(MyClass)
How can I exclude a public property of it?
(It has to be public, as I use it in my code somewhere else)
I have a DTO class which I Serialize
Json.Serialize(MyClass)
How can I exclude a public property of it?
(It has to be public, as I use it in my code somewhere else)
EDIT 2023-06-29: updated answer and added info about .NET core and System.Text.Json
If you don't want to decorate properties with some attributes, or if you have no access to the class, or if you want to decide what to serialize during runtime, here's how you do it:
Newtonsoft solution is pretty simple:
//short helper class to ignore some properties from serialization
public class IgnorePropertiesResolver : DefaultContractResolver
{
private readonly HashSet<string> ignoreProps;
public IgnorePropertiesResolver(IEnumerable<string> propNamesToIgnore)
{
this.ignoreProps = new HashSet<string>(propNamesToIgnore);
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
if (this.ignoreProps.Contains(property.PropertyName))
{
property.ShouldSerialize = _ => false;
}
return property;
}
}
Usage
JsonConvert.SerializeObject(YourObject, new JsonSerializerSettings()
{ ContractResolver = new IgnorePropertiesResolver(new[] { "Prop1", "Prop2" }) });
Make sure you cache the ContractResolver
object if you decide to use this answer, otherwise performance may suffer.
I've published the code here in case anyone wants to add anything: https://github.com/jitbit/JsonIgnoreProps
System.Text.Json
.NET core uses System.Text.Json
by default, it's faster, but you don't have all the flexibility of Newtonsoft. However here some solutions for excluding properties at runtime:
In .NET 7 and above you can control which properties get serialized like described here: https://devblogs.microsoft.com/dotnet/system-text-json-in-dotnet-7/#example-conditional-serialization
In .NET 6 (and below) - you can cast to an interface (which I personally find the cleanest) or use a mapper. Both options are descibed in this answer https://mcmap.net/q/93897/-how-to-exclude-a-property-from-being-serialized-in-system-text-json-jsonserializer-serialize-using-a-jsonconverter
CamelCasePropertyNamesContractResolver
, just take your IgnorePropertiesResolver
(likely renaming to something more accurate considering the combination) and inherit from CamelCasePropertyNamesContractResolver
instead of directly from DefaultContractResolver
. –
Epidemiology public IgnorePropertiesResolver(params string[] propNamesToIgnore)
as your constructor so that the implementer can say new IgnorePropertiesResolver("Prop1", "Prop2")
–
Dewitt DeclaringType
(https://mcmap.net/q/93898/-newtonsoft-json-shouldserialize-and-inheritance). I've create it by passing declaringType to constructor and using it from CreateProperty
–
Cumuliform If you are using Json.Net attribute [JsonIgnore]
will simply ignore the field/property while serializing or deserialising.
public class Car
{
// included in JSON
public string Model { get; set; }
public DateTime Year { get; set; }
public List<string> Features { get; set; }
// ignored
[JsonIgnore]
public DateTime LastModified { get; set; }
}
Or you can use DataContract and DataMember attribute to selectively serialize/deserialize properties/fields.
[DataContract]
public class Computer
{
// included in JSON
[DataMember]
public string Name { get; set; }
[DataMember]
public decimal SalePrice { get; set; }
// ignored
public string Manufacture { get; set; }
public int StockCount { get; set; }
public decimal WholeSalePrice { get; set; }
public DateTime NextShipmentDate { get; set; }
}
Refer http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size for more details
IgnoreDataMember
does not work with the default JsonResult
serializer. –
Prerequisite [JsonIgnore]
is also a valid attribute in System.Text.Json.Serialization
for ASP.NET Core –
Basuto If you are using System.Web.Script.Serialization
in the .NET framework you can put a ScriptIgnore
attribute on the members that shouldn't be serialized. See the example taken from here:
Consider the following (simplified) case:
public class User { public int Id { get; set; } public string Name { get; set; } [ScriptIgnore] public bool IsComplete { get { return Id > 0 && !string.IsNullOrEmpty(Name); } } }
In this case, only the Id and the Name properties will be serialized, thus the resulting JSON object would look like this:
{ Id: 3, Name: 'Test User' }
PS. Don't forget to add a reference to "System.Web.Extensions
" for this to work
ScriptIgnore
in System.Web.Script.Serialization
namespace. –
Predatory EDIT 2023-06-29: updated answer and added info about .NET core and System.Text.Json
If you don't want to decorate properties with some attributes, or if you have no access to the class, or if you want to decide what to serialize during runtime, here's how you do it:
Newtonsoft solution is pretty simple:
//short helper class to ignore some properties from serialization
public class IgnorePropertiesResolver : DefaultContractResolver
{
private readonly HashSet<string> ignoreProps;
public IgnorePropertiesResolver(IEnumerable<string> propNamesToIgnore)
{
this.ignoreProps = new HashSet<string>(propNamesToIgnore);
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
if (this.ignoreProps.Contains(property.PropertyName))
{
property.ShouldSerialize = _ => false;
}
return property;
}
}
Usage
JsonConvert.SerializeObject(YourObject, new JsonSerializerSettings()
{ ContractResolver = new IgnorePropertiesResolver(new[] { "Prop1", "Prop2" }) });
Make sure you cache the ContractResolver
object if you decide to use this answer, otherwise performance may suffer.
I've published the code here in case anyone wants to add anything: https://github.com/jitbit/JsonIgnoreProps
System.Text.Json
.NET core uses System.Text.Json
by default, it's faster, but you don't have all the flexibility of Newtonsoft. However here some solutions for excluding properties at runtime:
In .NET 7 and above you can control which properties get serialized like described here: https://devblogs.microsoft.com/dotnet/system-text-json-in-dotnet-7/#example-conditional-serialization
In .NET 6 (and below) - you can cast to an interface (which I personally find the cleanest) or use a mapper. Both options are descibed in this answer https://mcmap.net/q/93897/-how-to-exclude-a-property-from-being-serialized-in-system-text-json-jsonserializer-serialize-using-a-jsonconverter
CamelCasePropertyNamesContractResolver
, just take your IgnorePropertiesResolver
(likely renaming to something more accurate considering the combination) and inherit from CamelCasePropertyNamesContractResolver
instead of directly from DefaultContractResolver
. –
Epidemiology public IgnorePropertiesResolver(params string[] propNamesToIgnore)
as your constructor so that the implementer can say new IgnorePropertiesResolver("Prop1", "Prop2")
–
Dewitt DeclaringType
(https://mcmap.net/q/93898/-newtonsoft-json-shouldserialize-and-inheritance). I've create it by passing declaringType to constructor and using it from CreateProperty
–
Cumuliform You can use [ScriptIgnore]
:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
[ScriptIgnore]
public bool IsComplete
{
get { return Id > 0 && !string.IsNullOrEmpty(Name); }
}
}
In this case the Id and then name will only be serialized
[ScriptIgnore]
in MVC Controller. Be warned though, if you are using SignalR, then you should use [JsonIgnore]
too. –
Judaea If you are not so keen on having to decorate code with Attributes as I am, esp when you cant tell at compile time what will happen here is my solution.
Using the Javascript Serializer
public static class JsonSerializerExtensions
{
public static string ToJsonString(this object target,bool ignoreNulls = true)
{
var javaScriptSerializer = new JavaScriptSerializer();
if(ignoreNulls)
{
javaScriptSerializer.RegisterConverters(new[] { new PropertyExclusionConverter(target.GetType(), true) });
}
return javaScriptSerializer.Serialize(target);
}
public static string ToJsonString(this object target, Dictionary<Type, List<string>> ignore, bool ignoreNulls = true)
{
var javaScriptSerializer = new JavaScriptSerializer();
foreach (var key in ignore.Keys)
{
javaScriptSerializer.RegisterConverters(new[] { new PropertyExclusionConverter(key, ignore[key], ignoreNulls) });
}
return javaScriptSerializer.Serialize(target);
}
}
public class PropertyExclusionConverter : JavaScriptConverter
{
private readonly List<string> propertiesToIgnore;
private readonly Type type;
private readonly bool ignoreNulls;
public PropertyExclusionConverter(Type type, List<string> propertiesToIgnore, bool ignoreNulls)
{
this.ignoreNulls = ignoreNulls;
this.type = type;
this.propertiesToIgnore = propertiesToIgnore ?? new List<string>();
}
public PropertyExclusionConverter(Type type, bool ignoreNulls)
: this(type, null, ignoreNulls){}
public override IEnumerable<Type> SupportedTypes
{
get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { this.type })); }
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
var result = new Dictionary<string, object>();
if (obj == null)
{
return result;
}
var properties = obj.GetType().GetProperties();
foreach (var propertyInfo in properties)
{
if (!this.propertiesToIgnore.Contains(propertyInfo.Name))
{
if(this.ignoreNulls && propertyInfo.GetValue(obj, null) == null)
{
continue;
}
result.Add(propertyInfo.Name, propertyInfo.GetValue(obj, null));
}
}
return result;
}
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
throw new NotImplementedException(); //Converter is currently only used for ignoring properties on serialization
}
}
PropertyExclusionConverter
can be turned into a PropertyInclusionConverter
. –
Dollarfish For C# 9's records it's [property: JsonIgnore]
using System.Text.Json.Serialization;
public record R(
string Text2
[property: JsonIgnore] string Text2)
For the classic style it's still just [JsonIgnore]
.
using System.Text.Json.Serialization;
public record R
{
public string Text {get; init; }
[JsonIgnore]
public string Text2 { get; init; }
}
If you are using System.Text.Json
then you can use [JsonIgnore]
.
FQ: System.Text.Json.Serialization.JsonIgnoreAttribute
Official Microsoft Docs: JsonIgnoreAttribute
As stated here:
The library is built-in as part of the .NET Core 3.0 shared framework.
For other target frameworks, install the System.Text.Json NuGet package. The package supports:
- .NET Standard 2.0 and later versions
- .NET Framework 4.6.1 and later versions
- .NET Core 2.0, 2.1, and 2.2
You can also use the [NonSerialized]
attribute
[Serializable]
public struct MySerializableStruct
{
[NonSerialized]
public string hiddenField;
public string normalField;
}
Indicates that a field of a serializable class should not be serialized. This class cannot be inherited.
If you're using Unity for example (this isn't only for Unity) then this works with UnityEngine.JsonUtility
using UnityEngine;
MySerializableStruct mss = new MySerializableStruct
{
hiddenField = "foo",
normalField = "bar"
};
Debug.Log(JsonUtility.ToJson(mss)); // result: {"normalField":"bar"}
Add System.Text.Json Version for dotnet core
For compile time, add [JsonIgnore] as suggested in the above answer.
For run time, JsonConverter needs to be added into the options.
First, create a JsonConverter for the type you want to exclude, for example ICollection<LabMethod>
below
public class LabMethodConverter : JsonConverter<ICollection<LabMethod>>
{
public override ICollection<LabMethod> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
//deserialize JSON into a ICollection<LabMethod>
return null;
}
public override void Write(Utf8JsonWriter writer, ICollection<LabMethod> value, JsonSerializerOptions options)
{
//serialize a ICollection<LabMethod> object
writer.WriteNullValue();
}
}
Then add to options when you serialize Json
var options = new JsonSerializerOptions();
options.Converters.Add(new LabMethodConverter());
var new_obj = Json(new { rows = slice, total = count }, options);
Serialize
method instead of the Json
method used in this answer, you can still pass in the options
object using the appropriate Serialize
method overload. –
Reconstruct © 2022 - 2024 — McMap. All rights reserved.
IgnoreDataMember
ScriptIgnore
JsonIgnore
depending on the serializer you use – Roughrider