Yesterday, I needed to add a property in a JSON file, I've done this using DefaultHandling, as mentioned in this previous question:
[JsonProperty("DIAGNOSTICS", DefaultValueHandling = DefaultValueHandling.Populate)]
public bool DIAGNOSTICS { get; set; }
Now I'm dealing with a more complicated situation:
Excerpt of my source code:
[JsonProperty("NAME")]
public string NAME { get; set; }
[JsonProperty("i1.ENABLE")]
public bool i1ENABLE { get; set; }
[JsonProperty("i2.ENABLE")]
public bool i2ENABLE { get; set; }
[JsonProperty("i3ENABLE")]
public bool i3ENABLE { get; set; }
...
Desired JSON result:
"NAME": "i1",
"i1.ENABLE": false, /* i2.ENABLE and i3.ENABLE are not shown */
...
"NAME": "i2",
"i2.ENABLE": false, /* i1.ENABLE and i3.ENABLE are not shown */
...
"NAME": "i3",
"i3.ENABLE": false, /* i1.ENABLE and i2.ENABLE are not shown */
...
So my question is, is this possible (pseudo-code) and in case yes, how?
[JsonProperty("i1.ENABLE", DefaultValueHandling = (IF(NAME=="i1") THEN DefaultValueHandling.Populate))]
public bool i1ENABLE { get; set; }
[JsonProperty("i2.ENABLE", DefaultValueHandling = (IF(NAME=="i2") THEN DefaultValueHandling.Populate))]
public bool i2ENABLE { get; set; }
[JsonProperty("i3.ENABLE", DefaultValueHandling = (IF(NAME=="i3") THEN DefaultValueHandling.Populate))]
public bool i3ENABLE { get; set; }
Edit (after first answer from Laurent)
My serialisation code is the following:
JsonSerializerSettings js = new JsonSerializerSettings();
js.DefaultValueHandling = DefaultValueHandling.Ignore;
string temp = JsonConvert.SerializeObject(root, Formatting.Indented, js);
In case it can't be done in the property declaration, can it be done here?
You cannot have conditions in your attributes, try setting these conditional default values in regular code instead. (Attributes can only have constant values)
You could make use of the Conditional Property Serialization of json.net
class CC {
[JsonProperty("NAME")]
public string NAME { get; set; }
[JsonProperty("i1.ENABLE")]
public bool i1ENABLE { get; set; }
[JsonProperty("i2.ENABLE")]
public bool i2ENABLE { get; set; }
[JsonProperty("i3.ENABLE")]
public bool i3ENABLE { get; set; }
public bool ShouldSerializei1ENABLE() {
bool r = NAME == "i1";
return r;
}
public bool ShouldSerializei2ENABLE() {
bool r = NAME == "i2";
return r;
}
public bool ShouldSerializei3ENABLE() {
bool r = NAME == "i3";
return r;
}
}
So a property will only be serialized if ShouldSerialize[PropertyName]() returns true;
See also this fiddle
EDIT
Yes, the DefaultValueHandling.Ignore in your JsonSerializerSettings may indeed have an influence on the result of the serialization. Ie, even if ShouldSerialize... returns true, a property won't be serialized if it equals to the default value (in this particular case a bool will never be serialized, if it's false and DefaultValueHandling.Ignore is set).
So, if you always want to serialize i1ENABLE when NAME equals i1, you have to override the DefaultValueHandling for this property.
class CC {
[JsonProperty("NAME")]
public string NAME { get; set; }
[JsonProperty("i1.ENABLE", DefaultValueHandling=DefaultValueHandling.Populate)]
public bool i1ENABLE { get; set; }
public bool ShouldSerializei1ENABLE() {
bool r = NAME == "i1";
return r;
}
}
So when you serialize as follows
JsonSerializerSettings js = new JsonSerializerSettings();
js.DefaultValueHandling = DefaultValueHandling.Ignore;
string temp = JsonConvert.SerializeObject(root, Formatting.Indented, js);
the property i1ENABLE will always be serialized, when NAME == "i1" but never be serialized when NAME != "i1"
ShouldSerialize... is probably one of the first filters, that is done during serialization of a property. If it returns false, this property is never serialized. But if it returns true, there are still other checks. One of them is DefaultValueHandling. So if DefaultValueHandling is set to Ignore a boolean with value false won't be serialized, even if ShouldSerialize... returns true.
Please see also this updated fiddle
Related
I'm probably missing something.
I'd like to test behavior when an API call response returns a property of null and I would like to throw an exception when that happens.
I have a Form object as follow
public class Form
{
[Required]
public string Html { get; set; }
public string Json { get; set; }
public string Name { get; set; }
}
I have initialized an object
var myData = new
{
Json = "foo",
};
string jsonData = JsonConvert.SerializeObject(myData);
var response = JsonConvert.DeserializeObject<Form>(File.ReadAllText(jsonPath));
I was expecting to have an exception since the Html property is required and not nullable,
but actually getting the object as
{
Html = null,
Json = foo,
Name = null
}
I have tried to use JsonSerializerSettings as follows but this actually throws an exception only when there is an additional unwanted property and not when there's a missing one.
JsonSerializerSettings config = new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Error, NullValueHandling = NullValueHandling.Include};
var res = JsonConvert.DeserializeObject<Form>(json,config);
You need [JsonProperty(Required = Required.Always)].
public class Form
{
[JsonProperty(Required = Required.Always)]
public string Html { get; set; }
public string Json { get; set; }
public string Name { get; set; }
}
Sample Program
While [Required] attribute is for Data Annotation.
Reference
JsonPropertyAttribute required
I have following Json-based configuration file:
{
"PostProcessing": {
"ValidationHandlerConfiguration": {
"MinimumTrustLevel": 80,
"MinimumMatchingTrustLevel": 75
},
"MatchingCharacterRemovals": [
"-",
"''",
":"
]
},
"Processing": {
"OrderSelection": {
"SelectionDaysInterval": 30,
"SelectionDaysMaximum": 365
}
}
}
As serialization framework I use Newtonsoft. To serialize this config into objects I have implemented following classes:
[JsonObject(MemberSerialization.OptIn)]
public class RecognitionConfiguration {
[JsonProperty(PropertyName = "PostProcessing", Required = Required.Always)]
public PostRecognitionConfiguration PostRecognitionConfiguration { get; set; }
[JsonProperty(PropertyName = "Processing", Required = Required.Always)]
public ProcessRecognitionConfiguration ProcessRecognitionConfiguration { get; set; }
}
[JsonObject(MemberSerialization.OptIn)]
public class PostRecognitionConfiguration {
[JsonProperty(Required = Required.Always)]
public ValidationHandlerConfiguration ValidationHandlerConfiguration { get; set; }
[JsonProperty] public List<string> MatchingCharacterRemovals { get; set; }
}
[JsonObject(MemberSerialization.OptIn)]
public class ProcessRecognitionConfiguration {
[JsonProperty(PropertyName = "OrderSelection", Required = Required.Always)]
public OrderSelectionConfiguration OrderSelectionConfiguration { get; set; }
}
In a class I try to serialize a specific configuration section into these class structures using IConfigurationSection.Get().
var serializedConfiguration = this.ConfigurationSection.Get<RecognitionConfiguration>();
But when I debug the code, I always get an "empty" variable serializedConfiguration which is not null, but all properties are null.
If I use
this.ConfigurationSection.GetSection("Processing").Get<ProcessRecognitionConfiguration>()
or change the naming of the properties in the json file to exactly match the property names in the classes like this:
{
"ProcessRecognitionConfiguration": {
"OrderSelectionConfiguration": {
"SelectionDaysInterval": 30,
"SelectionDaysMaximum": 365
}
}
}
it it works fine. Do you have any idea, why setting PropertyName on JsonProperty does not seem to have any effect?
That is by design. Binding to POCO via configuration is done by convention. Not like Model Binding to Controller Action parameters.
It matches property names on the POCO to keys in the provided JSON.
Reference Configuration in ASP.NET Core
So either you change the settings to match the class like you showed in the original question, or change the class to match the settings keys in the Json-based configuration file.
[JsonObject(MemberSerialization.OptIn)]
public class RecognitionConfiguration {
[JsonProperty(PropertyName = "PostProcessing", Required = Required.Always)]
public PostRecognitionConfiguration PostProcessing{ get; set; }
[JsonProperty(PropertyName = "Processing", Required = Required.Always)]
public ProcessRecognitionConfiguration Processing{ get; set; }
}
[JsonObject(MemberSerialization.OptIn)]
public class PostRecognitionConfiguration {
[JsonProperty(Required = Required.Always)]
public ValidationHandlerConfiguration ValidationHandlerConfiguration { get; set; }
[JsonProperty]
public List<string> MatchingCharacterRemovals { get; set; }
}
[JsonObject(MemberSerialization.OptIn)]
public class ProcessRecognitionConfiguration {
[JsonProperty(PropertyName = "OrderSelection", Required = Required.Always)]
public OrderSelectionConfiguration OrderSelection { get; set; }
}
public partial class ValidationHandlerConfiguration {
[JsonProperty("MinimumTrustLevel")]
public long MinimumTrustLevel { get; set; }
[JsonProperty("MinimumMatchingTrustLevel")]
public long MinimumMatchingTrustLevel { get; set; }
}
public partial class OrderSelectionConfiguration {
[JsonProperty("SelectionDaysInterval")]
public long SelectionDaysInterval { get; set; }
[JsonProperty("SelectionDaysMaximum")]
public long SelectionDaysMaximum { get; set; }
}
EDIT: I found this one is much more pleasant than my previous solutions: Bind everything in an ExpandoObject, write them to JSON and use JSON.NET to bind them back. Using the code of this article:
namespace Microsoft.Extensions.Configuration
{
public static class ConfigurationBinder
{
public static void BindJsonNet(this IConfiguration config, object instance)
{
var obj = BindToExpandoObject(config);
var jsonText = JsonConvert.SerializeObject(obj);
JsonConvert.PopulateObject(jsonText, instance);
}
private static ExpandoObject BindToExpandoObject(IConfiguration config)
{
var result = new ExpandoObject();
// retrieve all keys from your settings
var configs = config.AsEnumerable();
foreach (var kvp in configs)
{
var parent = result as IDictionary<string, object>;
var path = kvp.Key.Split(':');
// create or retrieve the hierarchy (keep last path item for later)
var i = 0;
for (i = 0; i < path.Length - 1; i++)
{
if (!parent.ContainsKey(path[i]))
{
parent.Add(path[i], new ExpandoObject());
}
parent = parent[path[i]] as IDictionary<string, object>;
}
if (kvp.Value == null)
continue;
// add the value to the parent
// note: in case of an array, key will be an integer and will be dealt with later
var key = path[i];
parent.Add(key, kvp.Value);
}
// at this stage, all arrays are seen as dictionaries with integer keys
ReplaceWithArray(null, null, result);
return result;
}
private static void ReplaceWithArray(ExpandoObject parent, string key, ExpandoObject input)
{
if (input == null)
return;
var dict = input as IDictionary<string, object>;
var keys = dict.Keys.ToArray();
// it's an array if all keys are integers
if (keys.All(k => int.TryParse(k, out var dummy)))
{
var array = new object[keys.Length];
foreach (var kvp in dict)
{
array[int.Parse(kvp.Key)] = kvp.Value;
}
var parentDict = parent as IDictionary<string, object>;
parentDict.Remove(key);
parentDict.Add(key, array);
}
else
{
foreach (var childKey in dict.Keys.ToList())
{
ReplaceWithArray(input, childKey, dict[childKey] as ExpandoObject);
}
}
}
}
}
Usage:
var settings = new MySettings();
this.Configuration.BindJsonNet(settings);
Here is my testing MySettings class:
public class MySettings
{
[JsonProperty("PostProcessing")]
public SomeNameElseSettings SomenameElse { get; set; }
public class SomeNameElseSettings
{
[JsonProperty("ValidationHandlerConfiguration")]
public ValidationHandlerConfigurationSettings WhateverNameYouWant { get; set; }
public class ValidationHandlerConfigurationSettings
{
[JsonProperty("MinimumTrustLevel")]
public int MinimumTrustLevelFoo { get; set; }
[JsonProperty("MinimumMatchingTrustLevel")]
public int MinimumMatchingTrustLevelBar { get; set; }
}
}
}
After the calling, I get everything as you desired:
Old Answer:
According to the source code here, it is simply (near) impossible to do what you are requiring. I have tried both JsonProperty and DataContract, none of which are honored by the Binder, simply because the source code itself simply use the property name.
If you still insist, there are 2 possibilities, however I do not recommend any as changing properties' names are much simpler:
Fork your source code there, or simply copy that file (in my attempt to trace the code, I rename all methods to something like Bind2, BindInstance2 etc), and rewrite the code accordingly.
This one is very specific to current implementation, so it's not future-proof: the current code is calling config.GetSection(property.Name), so you can write your own IConfiguration and provide your own name for GetSection method and tap it into the bootstrap process instead of using the default one.
Changing PropertyName on JsonProperty does have effect. Here is the same I tried and it did worked for me:
my JSON data:
{"name": "John","age": 30,"cars": [ "Ford", "BMW", "Fiat" ]}
and the Model:
public class RootObject
{
[JsonProperty(PropertyName ="name")]
public string Apple { get; set; }
public int age { get; set; }
public List<string> cars { get; set; }
}
and here is the code:
RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);
and this is the output i get
You need to set the PropertyName in JsonProperty same as json file property name but your C# model property can be what you wanted, just that they need to be decorated with [JsonProperty(PropertyName ="jsonPropertyName")] Hope this helps you solve your issue.
Happy coding...
I am receiving JSON data from a web API that looks like this:
[
{
"id": 1
"error_message": "An error has occurred!"
}
]
I deserialize this data to objects of the following type:
public class ErrorDetails
{
public int Id { get; set; }
[JsonProperty("error_message")]
public string ErrorMessage { get; set; }
}
Later in my application I would like to serialize the ErrorDetails object again to JSON but using the property name ErrorMessage instead of error_message. So the result would look like this:
[
{
"Id": 1
"ErrorMessage": "An error has occurred!"
}
]
Is there an easy way I can accomplish this with Json.Net? Perhaps using a custom resolver and some attributes like:
public class ErrorDetails
{
public int Id { get; set; }
[SerializeAs("ErrorMessage")]
[DeserializeAs("error_message")]
public string ErrorMessage { get; set; }
}
But the resolver doesn't tell me when I'm serializing or deserializing.
You can make use of the JsonSerializerSettings, the ContractResolver and the NamingStrategy.
public class ErrorDetails
{
public int Id { get; set; }
public string ErrorMessage { get; set; }
}
var json = "{'Id': 1,'error_message': 'An error has occurred!'}";
For dezerialization you could use the SnakeCaseNamingStrategy.
var dezerializerSettings = new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver
{
NamingStrategy = new SnakeCaseNamingStrategy()
}
};
var obj = JsonConvert.DeserializeObject<ErrorDetails>(json, dezerializerSettings);
To serialize the object again you dont have to change the JsonSerializerSettings as the default will use the property name.
var jsonNew = JsonConvert.SerializeObject(obj);
jsonNew = "{'Id': 1,'ErrorMessage': 'An error has occurred!'}"
Or you could create a contract resolver which can decide which name to use. Then you can decide when you dezerialize and serialize if you want to use the pascal case name format or the one with the underscore.
public class CustomContractResolver : DefaultContractResolver
{
public bool UseJsonPropertyName { get; }
public CustomContractResolver(bool useJsonPropertyName)
{
UseJsonPropertyName = useJsonPropertyName;
}
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = base.CreateProperty(member, memberSerialization);
if (!UseJsonPropertyName)
property.PropertyName = property.UnderlyingName;
return property;
}
}
public class ErrorDetails
{
public int Id { get; set; }
[JsonProperty("error_message")]
public string ErrorMessage { get; set; }
}
var json = "{'Id': 1,'error_message': 'An error has occurred!'}";
var serializerSettings = new JsonSerializerSettings()
{
ContractResolver = new CustomContractResolver(false)
};
var dezerializerSettings = new JsonSerializerSettings
{
ContractResolver = new CustomContractResolver(true)
};
var obj = JsonConvert.DeserializeObject<ErrorDetails>(json, dezerializerSettings);
var jsonNew = JsonConvert.SerializeObject(obj, serializerSettings);
jsonNew = "{'Id': 1,'ErrorMessage': 'An error has occurred!'}"
Another way of achieving a different property name when serialising vs deserisalising is by using the ShouldSerialize method: https://www.newtonsoft.com/json/help/html/ConditionalProperties.htm#ShouldSerialize
The docs say:
To conditionally serialize a property, add a method that returns
boolean with the same name as the property and then prefix the method
name with ShouldSerialize. The result of the method determines whether
the property is serialized. If the method returns true then the
property will be serialized, if it returns false then the property
will be skipped.
E.g:
public class ErrorDetails
{
public int Id { get; set; }
// This will deserialise the `error_message` property from the incoming json into the `GetErrorMessage` property
[JsonProperty("error_message")]
public string GetErrorMessage { get; set; }
// If this method returns false then the property after the `ShouldSerialize` prefix will not be serialised into the output
public bool ShouldSerializeGetErrorMessage() => false;
// The serialised output will return `ErrorMessage` with the value from `GetErrorMessage` i.e. `error_message` in the original json
public string ErrorMessage { get { return GetErrorMessage; } }
}
This results in slightly more overhead so be careful if dealing with lots of properties or with lots of data but for small payloads, and if you don't mind messing up your DTO class a little, then this could be a quicker solution than writing custom contract resolvers etc.
I liked the answer by #lee_mcmullen, and implemented it in my own code. Now I think I've found a slightly neater version.
public class ErrorDetails
{
public int Id { get; set; }
// This will deserialise the `error_message` property from the incoming json and store it in the new `GetErrorMessage` property
[JsonProperty("error_message")]
public string GetErrorMessage { get { return ErrorMessage; } set { ErrorMessage = value; } }
// If this method returns false then the property after the `ShouldSerialize` prefix will not be serialised into the output
public bool ShouldSerializeGetErrorMessage() => false;
// The serialised output will return `ErrorMessage` with the value set from `GetErrorMessage` i.e. `error_message` in the original json
public string ErrorMessage { get; set; }
}
The reason I like this better is that in more complicated models it allows for inheritance while keeping all of the "old" custom stuff separate
public class ErrorDetails
{
public int Id { get; set; }
public string ErrorMessage { get; set; }
}
// This is our old ErrorDetails that hopefully we can delete one day
public class OldErrorDetails : ErrorDetails
{
// This will deserialise the `error_message` property from the incoming json and store it in the new `GetErrorMessage` property
[JsonProperty("error_message")]
public string GetErrorMessage { get { return ErrorMessage; } set { ErrorMessage = value; } }
// If this method returns false then the property after the `ShouldSerialize` prefix will not be serialised into the output
public bool ShouldSerializeGetErrorMessage() => false;
}
I'm communicating with a JSON-based API which I can't change. It always returns a Response object with a varying Result object inside. Typically it looks like this:
{ "ver": "2.0", "result": { "code": 0 } }
For certain commands the Result object is 'grown' by adding extra properties:
{ "ver": "2.0", "result": { "code": 0, "hostName": "sample", "hostPort": 5000 } }
I've used Newtonsoft attributes to define the objects as follows:
internal class RpcResponse
{
[JsonProperty(PropertyName = "ver")]
public string Version { get; set; }
[JsonProperty(PropertyName = "result")]
public RpcResponseResult Result
{
get;
set;
}
internal class RpcResponseResult
{
[JsonProperty(PropertyName = "code")]
public int Code { get; set; }
}
internal class RpcExtendedResponseResult: RpcResponseResult
{
[JsonProperty(PropertyName = "hostName")]
public string HostName { get; set; }
[JsonProperty(PropertyName = "hostPort")]
public int HostPort { get; set; }
But when the Response object is deserialized:
RpcResponse rspResponse = JsonConvert.DeserializeObject<RpcResponse>(rspString);
Its Result property always appears as an RpcResponseResult object, ie. JsonConvert doesn't know to construct it as a RpcExtendedResponseResult object.
Is there some way with Attributes or Converters to reinstate the correct descendent object? I feel like I'm missing something obvious!
It's because the type of the object is RpcResponseResult. The deserializer can only deserialize fields that are declared in the type of the field specified. It can't determine because a class has "hostName" its now an RpcExtendedResponseResult.
If I were doing this, I might make the result a container for all possible fields with default values if needed, and then you can fill another object as needed.
internal class RpcResponseResultContainer
{
[JsonProperty(PropertyName = "code")]
public int Code { get; set; }
[JsonProperty(PropertyName = "hostName")]
private string mHostName = string.Empty;
public string HostName
{
get { return mHostName;}
set { mHostName = value; }
}
[JsonProperty(PropertyName = "hostPort")]
private int mHostPort = -1;
public int HostPort
{
get { return mHostPort;}
set { mHostPort = value;}
}
Then if you really wanted to get your object as you want it, you could do something like this in your container class:
public RpcResponseResult GetActualResponseType()
{
if(HostPort != -1 && !string.IsNullOrEmtpy(HostName))
{
return new RpcExtendedResponseResult() { Code = this.Code, HostName = this.HostName, HostPort = this.HostPort};
}
return new RpcResponseResult() { Code = this.Code };
}
First, credit to Matthew Frontino for providing the only answer which I've accepted.
However I opted not to make a single result container, so here's what I ended up doing.
First I started with this page: How to implement custom JsonConverter in JSON.NET to deserialize a List of base class objects?
I used the version of JsonCreationConverter provided there by Alain.
I added the CanWrite override as suggested there by Dribbel:
public override bool CanWrite
{
get { return false; }
}
I also added my own helper function to JsonCreationConverter:
protected bool FieldExists(string fieldName, JObject jObject) {
return jObject[fieldName] != null;
}
Then I created my own converter as follows:
class RpcResponseResultConverter : JsonCreationConverter<RpcResponseResult>
{
protected override RpcResponseResult Create(Type objectType, JObject jObject)
{
// determine extended responses
if (FieldExists("hostName", jObject) &&
FieldExists("hostPort", jObject) )
{
return new RpcExtendedResponseResult();
}
//default
return new RpcResponseResult();
}
}
Then I deserialize the top-level class and supply any converters to be used. In this case I only supplied one, which was for the nested class in question:
RpcResponse rspResponse = JsonConvert.DeserializeObject<RpcResponse>(
rspString,
new JsonSerializerSettings {
DateParseHandling = Newtonsoft.Json.DateParseHandling.None,
Converters = new List<JsonConverter>( new JsonConverter[] {
new RpcResponseResultConverter()
})
});
Notes:
Anything not explicitly handled by a converter (such as the top-level class) is deserialized using the default converter built into JsonConvert.
This only works if you can identify a unique set of fields for every descendent class.
I'm using JSON.NET as my main serializer.
This is my model, look that I've setted some JSONProperties and a DefaultValue.
public class AssignmentContentItem
{
[JsonProperty("Id")]
public string Id { get; set; }
[JsonProperty("Qty")]
[DefaultValue(1)]
public int Quantity { get; set; }
}
When I serialize a List<AssignmentContentItem>, it doing a good work:
private static JsonSerializerSettings s = new JsonSerializerSettings
{
DefaultValueHandling = DefaultValueHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore
};
OUTPUT:
[{"Id":"Q0"},{"Id":"Q4"},{"Id":"Q7"}]
But when I'd like to deserialize this jsonContent, the property Qty is always 0 and is not set to the default value. I mean, when I deserialize that jsonContent, as DefaultValue for Quantity should be one instead of 0.
public static List<AssignmentContentItem> DeserializeAssignmentContent(string jsonContent)
{
return JsonConvert.DeserializeObject<List<AssignmentContentItem>>(jsonContent, s);
}
What should I do
The DefaultValue attribute does not set the value of the property. See this question: .NET DefaultValue attribute
What you might be better off doing is setting the value in the constructor:
public class AssignmentContentItem
{
[JsonProperty("Id")]
public string Id { get; set; }
[JsonProperty("Qty")]
public int Quantity { get; set; }
public AssignmentContentItem()
{
this.Quantity = 1;
}
}
Where this line:
AssignmentContentItem item =
JsonConvert.DeserializeObject<AssignmentContentItem>("{\"Id\":\"Q0\"}");
Results in an AssignmentContentItem with its Quantity set to 1.
You can use the the DefaultValueHandling.Populate setting so that Json.Net will populate the created object with the default value.
public static List<AssignmentContentItem> DeserializeAssignmentContent(string jsonContent)
{
return JsonConvert.DeserializeObject<List<AssignmentContentItem>>(jsonContent, new JsonSerializerSettings
{
DefaultValueHandling = DefaultValueHandling.Populate,
NullValueHandling = NullValueHandling.Ignore
});
}
http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_DefaultValueHandling.htm