using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System.ComponentModel.DataAnnotations;
using System.Globalization;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Serialization;
public static class JTokenExtensions
const string XsiNamespace = @"http://www.w3.org/2001/XMLSchema-instance";
readonly static string XmlNullValue = System.Xml.XmlConvert.ToString(true);
public static JToken ReplaceXmlNilObjectsWithNull(this JToken root)
return root.ReplaceXmlNilObjects(t => JValue.CreateNull());
public static JToken ReplaceXmlNilObjects(this JToken root, Func<JToken, JToken> getReplacement)
var query = from obj in root.DescendantsAndSelf().OfType<JObject>()
where obj.Properties().Any(p => p.IsNilXmlTrueProperty())
foreach (var obj in query.ToList())
var replacement = getReplacement(obj);
obj.Replace(replacement);
static IEnumerable<JToken> DescendantsAndSelf(this JToken node)
return Enumerable.Empty<JToken>();
var container = node as JContainer;
return container.DescendantsAndSelf();
static string GetXmlNamespace(this JProperty prop)
if (!prop.Name.StartsWith("@"))
var index = prop.Name.IndexOf(":");
if (index < 0 || prop.Name.IndexOf(":", index+1) >= 0)
var ns = prop.Name.Substring(1, index - 1);
if (string.IsNullOrEmpty(ns))
var nsPropertyName = "@xmlns:" + ns;
foreach (var obj in prop.AncestorsAndSelf().OfType<JObject>())
var nsProperty = obj[nsPropertyName];
if (nsProperty != null && nsProperty.Type == JTokenType.String)
return (string)nsProperty;
static bool IsNilXmlTrueProperty(this JProperty prop)
if (!(prop.Value.Type == JTokenType.String && (string)prop.Value == "true"))
if (!(prop.Name.StartsWith("@") && prop.Name.EndsWith(":nil")))
var ns = prop.GetXmlNamespace();
return ns == XsiNamespace;
public List<DateTime?> AustrittDatum { get; set; }
public static void Test()
foreach (var xmlString in GetXml())
Console.WriteLine("\nInput XML: ");
Console.WriteLine(xmlString);
var xDoc = XDocument.Parse(xmlString);
var converter = new Newtonsoft.Json.Converters.XmlNodeConverter { OmitRootObject = true };
var rootToken = JObject.FromObject(xDoc, JsonSerializer.CreateDefault(new JsonSerializerSettings { Converters = { converter } } ))
.ReplaceXmlNilObjectsWithNull();
var rootObject = rootToken.ToObject<RootObject>();
Console.WriteLine("Intermediate JSON: ");
Console.WriteLine(rootToken);
Console.WriteLine("Final deserialized and re-serialized {0}", rootObject);
Console.WriteLine(JsonConvert.SerializeObject(rootObject, Newtonsoft.Json.Formatting.Indented));
Assert.IsTrue(!rootToken.ToString(Newtonsoft.Json.Formatting.None).Contains(@"""@xsi:nil"": ""true"""));
static IEnumerable<string> GetXml()
<AustrittDatum>2018-01-31+01:00</AustrittDatum>
<AustrittDatum xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:nil=""true""/>""
@"<Root xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" >
<AustrittDatum>2018-01-31+01:00</AustrittDatum>
<AustrittDatum xsi:nil=""true""/>""
public static void Main()
Console.WriteLine("Environment version: " + Environment.Version);
Console.WriteLine("Json.NET version: " + typeof(JsonSerializer).Assembly.FullName);
Console.WriteLine("Failed with unhandled exception: ");
public class AssertionFailedException : System.Exception
public AssertionFailedException() : base() { }
public AssertionFailedException(string s) : base(s) { }
public static class Assert
public static void IsTrue(bool value)
public static void IsTrue(bool value, string message)
throw new AssertionFailedException(message ?? "failed");