Making a property deserialize but not serialize with json.net
There are actually several fairly simple approaches you can use to achieve the result you want.
Let's assume, for example, that you have your classes currently defined like this:
class Config
{
public Fizz ObsoleteSetting { get; set; }
public Bang ReplacementSetting { get; set; }
}
enum Fizz { Alpha, Beta, Gamma }
class Bang
{
public string Value { get; set; }
}
And you want to do this:
string json = @"{ ""ObsoleteSetting"" : ""Gamma"" }";
// deserialize
Config config = JsonConvert.DeserializeObject<Config>(json);
// migrate
config.ReplacementSetting =
new Bang { Value = config.ObsoleteSetting.ToString() };
// serialize
json = JsonConvert.SerializeObject(config);
Console.WriteLine(json);
To get this:
{"ReplacementSetting":{"Value":"Gamma"}}
Approach 1: Add a ShouldSerialize methodJson.NET has the ability to conditionally serialize properties by looking for corresponding ShouldSerialize
methods in the class.
To use this feature, add a boolean ShouldSerializeBlah()
method to your class where Blah
is replaced with the name of the property that you do not want to serialize. Make the implementation of this method always return false
.
class Config
{
public Fizz ObsoleteSetting { get; set; }
public Bang ReplacementSetting { get; set; }
public bool ShouldSerializeObsoleteSetting()
{
return false;
}
}
Note: if you like this approach but you don't want to muddy up the public interface of your class by introducing a ShouldSerialize
method, you can use an IContractResolver
to do the same thing programmatically. See Conditional Property Serialization in the documentation.
Instead of using JsonConvert.SerializeObject
to do the serialization, load the config object into a JObject
, then simply remove the unwanted property from the JSON before writing it out. It's just a couple of extra lines of code.
JObject jo = JObject.FromObject(config);
// remove the "ObsoleteSetting" JProperty from its parent
jo["ObsoleteSetting"].Parent.Remove();
json = jo.ToString();
Approach 3: Clever (ab)use of attributes- Apply a
[JsonIgnore]
attribute to the property that you do not want to be serialized. - Add an alternate, private property setter to the class with the same type as the original property. Make the implementation of that property set the original property.
- Apply a
[JsonProperty]
attribute to the alternate setter, giving it the same JSON name as the original property.
Here is the revised Config
class:
class Config
{
[JsonIgnore]
public Fizz ObsoleteSetting { get; set; }
[JsonProperty("ObsoleteSetting")]
private Fizz ObsoleteSettingAlternateSetter
{
// get is intentionally omitted here
set { ObsoleteSetting = value; }
}
public Bang ReplacementSetting { get; set; }
}
How to ignore a property from serialization but keep in for deserialization using json.net in c#
Could you have a method for the 'set' of Content
and process the data into the right place.
public class Foo
{
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("contentType")]
public object ContentType { get; set; }
[JsonProperty("content")]
public object Content { get; set {
//do something here with `value` e.g.
RelationshipContent = value; //change as required
DomainContent = value; //change as required
}
}
[JsonIgnore]
public Relationship RelationshipContent { get; set; }
[JsonIgnore]
public Domains DomainContent { get; set; }
}
Ignore some of the properties during Json.NET serializing but required on others
Try the below code
[JsonProperty(PropertyName = "componentMainVersion", DefaultValueHandling = DefaultValueHandling.Include)]
public ushort Version { get; set; }
Required is a different property which makes sure that value for the property is required always
Serialize Property, but Do Not Deserialize Property in Json.Net
Simplest method would be to mark the real property as [JsonIgnore]
and create a get-only proxy property:
/// <summary>
/// Gets or sets the country code, and province or state code delimited by a vertical pipe: <c>US|MI</c>
/// </summary>
[JsonIgnore]
public string CountryProvinceState
{
get
{
return string.Format("{0}|{1}", this.CountryCode, this.ProvinceState);
}
set
{
if (!string.IsNullOrWhiteSpace(value) && value.Contains("|"))
{
string[] valueParts = value.Split('|');
if (valueParts.Length == 2)
{
this.CountryCode = valueParts[0];
this.ProvinceState = valueParts[1];
}
}
}
}
[JsonProperty("countryProvinceState")]
string ReadCountryProvinceState
{
get { return CountryProvinceState; }
}
The proxy property can be private if you desire.
Update
If you have to do this for lots of properties in lots of classes, it might be easier to create your own ContractResolver
that checks for a custom attribute. If found, the attribute would signal that the property is get-only:
[System.AttributeUsage(System.AttributeTargets.Property, AllowMultiple = false)]
public class GetOnlyJsonPropertyAttribute : Attribute
{
}
public class GetOnlyContractResolver : DefaultContractResolver
{
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (property != null && property.Writable)
{
var attributes = property.AttributeProvider.GetAttributes(typeof(GetOnlyJsonPropertyAttribute), true);
if (attributes != null && attributes.Count > 0)
property.Writable = false;
}
return property;
}
}
Then use it like:
[JsonProperty("countryProvinceState")]
[GetOnlyJsonProperty]
public string CountryProvinceState { get; set; }
And then:
var settings = new JsonSerializerSettings { ContractResolver = new GetOnlyContractResolver() };
var address = JsonConvert.DeserializeObject<Address>(jsonString, settings);
Ignore a property when deserializing using Json.Net with ItemRequired = Required.Always
Evidently JsonIgnore
will only control the serialization in this case. JsonIgnore
is required to specify that the FullName
property should not be serialized to the json representation.
To ignore the property during deserialization we need to add the JsonProperty
annotation with Required = Required.Default
(which means not required).
So, this is how to avoid the JsonSerializationException
:
[JsonObject(ItemRequired = Required.Always)]
public class Hamster
{
public string FirstName { get; set; }
public string LastName { get; set; }
[JsonIgnore]
[JsonProperty(Required = Required.Default)]
public string FullName { get { return FirstName + LastName; }}
}
Can I instruct Json.NET to deserialize, but not serialize, specific properties?
You should be able to just use the ShouldSerialize* methods as shown in the question. These only impact serialization, not deserialization.
Json Serialize ignore properties when not assigning value but property should be present when assign null
To be more generic you have to create your own ContractResolver class
Step 1: Car class should be as following:
public class Car {
public int CarId { get; set; }
public string Brand { get; set; } = "null"; // Default value
public string Model { get; set; } = "null"; // Default value
public string Color { get; set; } = "null"; // Default value
}
Step 2: You will need to create the following class:
public class ShouldSerializeContractResolver : DefaultContractResolver {
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) {
JsonProperty property = base.CreateProperty(member, memberSerialization);
if (!property.PropertyName.Equals("CarId")) {
property.ShouldSerialize =
instance => {
var car = (Car)instance;
var value = car.GetType().GetProperty(property.PropertyName).GetValue(car, null);
return value == null || !value.ToString().Equals("null");
};
}
return property;
}
}
Step 3: create car object:
var car = new Car {
CarId = 1,
Brand = "Hundai",
Model = null
};
Step 4: Serialize the object - Notice how we create ContractResolver here :
var SerializedCar = JsonConvert.SerializeObject(car,
Formatting.Indented,
new JsonSerializerSettings {ContractResolver = new ShouldSerializeContractResolver()
});
Step 5: Print the output:
Console.WriteLine(SerializedCar);
Finally: The result:
{
"CarId": 1,
"Brand": "Hundai",
"Model": null
}
Related Topics
Filling a Character Array With Characters from a String
How to Map to a Dictionary Object from Database Results Using Dapper Dot Net
Asp.Net Core 2 Web API Timeout Issue
A Better Way to Use Automapper to Flatten Nested Objects
Using X-Alt-Desc/Applying HTML to Calendar Invites in Outlook
Json.Net: Deserilization With Double Quotes
How to Check If Multiple Values in an Array Are Equal to One String
Algorithm to Detect Overlapping Periods
How to Add a Run Button and Compile Button on the Toolbar in Visual Studio
Linq to SQL Left Outer Join Using Lambda Syntax and Joining on 2 Columns (Composite Join Key)
How to Delete a Read-Only File
Moq - Verify Exception Was Thrown
The Incoming Request Has Too Many Parameters. the Server Supports a Maximum of 2100 Parameters
How to Get a Specific Column Value from a Datatable
Parse Strings to Double With Comma and Point