using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System.Xml.Serialization;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
public string Id { get; set; }
[XmlElement(IsNullable = true)]
public DateTime? RenewalDate { get; set; }
public Vehicle Vehicle { get; set; }
public static partial class JTokenExtensions
public static bool WasNilXmlElement(this JToken token)
if (token.Type == JTokenType.Null)
var obj = token as JObject;
if (obj.Properties().All(p => p.Name.StartsWith("@"))
&& obj.Properties().Any(p => p.Name == "@nil" || p.Name.EndsWith(":nil") && p.Value.ToString() == "true"))
public static partial class JTokenExtensions
public static JToken ReplaceNilXmlElementObjectsWithNull(this JToken root)
var rootContainer = root as JContainer;
if (rootContainer == null)
var list = rootContainer.DescendantsAndSelf()
.Where(o => o.WasNilXmlElement())
foreach (var obj in list)
var replacement = JValue.CreateNull();
obj.Replace(replacement);
public static void Test()
Console.WriteLine("Testing deserialization of JSON: ");
var settings = new JsonSerializerSettings
var root = JsonConvert.DeserializeObject<JToken>(json, settings)
.ReplaceNilXmlElementObjectsWithNull()
.ToObject<RootObject[]>(JsonSerializer.CreateDefault(settings));
Assert.IsTrue(root.Length == 2
&& root[0].Vehicle.RenewalDate == null
&& root[1].Vehicle.RenewalDate == new DateTime(2017, 7, 16, 0, 0, 0, DateTimeKind.Utc));
Console.WriteLine("Deserialization and re-serialization successful, result: ");
Console.WriteLine(JsonConvert.SerializeObject(root, Newtonsoft.Json.Formatting.Indented));
Test(new RootObject { Vehicle = new Vehicle { Id = "101", RenewalDate = null } }, null);
Test(new RootObject { Vehicle = new Vehicle { Id = "101", RenewalDate = DateTime.UtcNow } }, null);
Console.WriteLine("\nAll tests passed successfully.");
static void Test<T>(T obj, JsonSerializerSettings settings)
private static void Test<T>(string xml, JsonSerializerSettings settings)
Console.WriteLine(string.Format("Testing round-trip of type {0} with input XML as follows: ", typeof(T)));
var json = JsonConvert.SerializeXNode(XElement.Parse(xml), Newtonsoft.Json.Formatting.Indented, true);
Console.WriteLine("Intermediate JSON: ");
var token = JsonConvert.DeserializeObject<JToken>(json, settings);
var obj2 = token.ReplaceNilXmlElementObjectsWithNull().ToObject<T>(JsonSerializer.CreateDefault(settings));
var xml2 = obj2.GetXml();
var ok = XNode.DeepEquals(XElement.Parse(xml), XElement.Parse(xml2));
Console.WriteLine("Input XML and reserialized XML are equivalent.");
""RenewalDate"": ""2017-07-16T00:00:00Z""
public class AssertionFailedException : System.Exception
public AssertionFailedException() : base() { }
public AssertionFailedException(string s) : base(s) { }
public static class Assert
public static void IsTrue(bool value)
throw new AssertionFailedException("failed");
public static partial class XmlSerializerExtensions
public static string GetXml<T>(this T obj, bool omitStandardNamespaces = true)
XmlSerializerNamespaces ns = null;
if (omitStandardNamespaces)
ns = new XmlSerializerNamespaces();
using (var textWriter = new StringWriter())
var settings = new XmlWriterSettings() { Indent = true };
using (var xmlWriter = XmlWriter.Create(textWriter, settings))
new XmlSerializer(obj.GetType()).Serialize(xmlWriter, obj, ns);
return textWriter.ToString();
public static void Main()
Console.WriteLine("Environment version: " + Environment.Version);
Console.WriteLine("Json.NET version: " + typeof(JsonSerializer).Assembly.FullName);