Reputation: 664
When serializing a dictionary with JSON.NET, it seems like the NullValueHandling
setting is ignored.
var dict = new Dictionary<string, string>
{
["A"] = "Some text",
["B"] = null
};
var json = JsonConvert.SerializeObject(dict, Formatting.Indented,
new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore
});
Console.WriteLine(json);
Output:
{
"A": "Some text",
"B": null
}
I expected that only the key-value pair with key "A" is present in the JSON output and the pair for "B" is omitted.
How can I tell JSON.NET to only serialize the entries that do not contain null values?
Upvotes: 7
Views: 6050
Reputation: 26315
I would just filter out the null
values from the original dictionary with LINQ and serialize the filtered dictionary:
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
namespace JsonSerialize {
public static class Program {
private static Dictionary<string, string> dict = new Dictionary<string, string> {
["A"] = "Some text",
["B"] = null
};
public static void Main(string[] args) {
var filtered = dict
.Where(p => p.Value != null)
.ToDictionary(p => p.Key, p => p.Value);
var json = JsonConvert.SerializeObject(filtered, Formatting.Indented);
Console.WriteLine (json);
}
}
}
Which gives:
{
"A": "Some text"
}
Upvotes: 4
Reputation: 71
The NullValueHandling
setting is only applicable to class properties and not dictionaries. There doesn't appear to be a built-in way in JSON.NET to ignore null values in a dictionary.
If you want JSON.NET to handle this case for you, then you can create a custom JSON converter and override the WriteJson
method to handle the null values.
public class CustomJsonConverter : JsonConverter
{
public override bool CanRead => false;
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Dictionary<string, string>);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var dictionary = (Dictionary<string, string>)value;
writer.WriteStartObject();
foreach (var pair in dictionary)
{
if (pair.Value != null)
{
writer.WritePropertyName(pair.Key);
serializer.Serialize(writer, pair.Value);
}
}
writer.WriteEndObject();
}
}
Which then you can use like this:
var json = JsonConvert.SerializeObject(dict, Formatting.Indented, new CustomJsonConverter());
Upvotes: 4
Reputation: 19033
The main idea of serialization is that after deserialization you should have the same object back. Most likely that is illogical to leave out keys with null
values from a dictionary because keys per se represent some data. But that is ok to not save null fields because after deserialization you would still have the same object because these fields would be initialized to null
by default.
And, this would work fine for class fields if they are null
s. Look at this example:
public class Movie
{
public string Name { get; set; }
public string Description { get; set; }
public string Classification { get; set; }
public string Studio { get; set; }
public DateTime? ReleaseDate { get; set; }
public List<string> ReleaseCountries { get; set; }
}
Movie movie = new Movie();
movie.Name = "Bad Boys III";
movie.Description = "It's no Bad Boys";
string ignored = JsonConvert.SerializeObject(movie,
Formatting.Indented,
new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
// {
// "Name": "Bad Boys III",
// "Description": "It's no Bad Boys"
// }
In your case values for certain keys are null
s, but that's not the same as in the documentation provided.
This might help you, but you should be aware of how ToDictionary
affects performance:
var json = JsonConvert.SerializeObject(dict.Where(p => p.Value != null)
.ToDictionary(p => p.Key, p => p.Value), Formatting.Indented);
Upvotes: 2