How to prevent “Date & Time” conversion while converting a json string to XML doc

梦想的初衷 提交于 2020-01-30 09:32:11

问题


I want to convert a JSON response to an equivalent XML document but while doing so, I also want to preserve current date and time format along with the offset e.g., DateTime in JSON is "2019-10-25T07:00:00-05:00" and after conversion I want it to remain the same. But after conversion into XML, the DateTime value becomes "2019-10-25T08:00:00-04:00"

I tried to search about it in Microsoft docs but I didn't find my answer for the following questions:

  1. How to determine the time zone of a given date time string (e.g., "2019-10-25T07:00:00-05:00")?
  2. How can I convert a date time string (e.g., "2019-10-25T08:00:00-04:00") into a date time of the desired time-zone (e.g., into the time zone of "2019-10-25T07:00:00-05:00")
// C# Code Snippet
// Step 1: Reading JsonResponse from a file
string jsonString = System.IO.File.ReadAllText(@"C:\TestDateTimeConvertJSONResponse.txt");
// Step 2: Converting jsonString to XMLDoc
System.Xml.XmlDocument xmlDoc = Newtonsoft.Json.JsonConvert.DeserializeXmlNode(jsonString);
Console.WriteLine();
Console.WriteLine("EQUIVALENT XML RESPONSE");
Console.WriteLine(xmlDoc.InnerXml);

Input JSON string:

{
    "Flight": {
        "FlightNumber": "747",
        "Source": "JFK",
        "Destination": "LAS",   
        "Status": "ON TIME",
        "DepDateTime": "2019-10-25T07:00:00-05:00",
        "Terminal": "2"
    }
}

Expected:

<Flight>
    <FlightNumber>747</FlightNumber>
    <Source>JFK</Source>
    <Destination>LAS</Destination>
    <Status>ON TIME</Status>
    <DepDateTime>2019-10-25T07:00:00-05:00</DepDateTime>
    <Terminal>2</Terminal>
</Flight>

Actual:

<Flight>
    <FlightNumber>747</FlightNumber>
    <Source>JFK</Source>
    <Destination>LAS</Destination>
    <Status>ON TIME</Status>
    <DepDateTime>2019-10-25T08:00:00-04:00</DepDateTime>
    <Terminal>2</Terminal>
</Flight>

回答1:


Your problem is that Json.NET's automatic DateTime recognition recognizes that the string "2019-10-25T07:00:00-05:00" is a valid ISO 8601 date and time and parses it to a DateTime -- which unfortunately does not have support for timezone specification. Thus the value gets converted (correctly) to the local timezone on your computer during deserialization and subsequently formatted as such in the XML.

To prevent this, you need to parse the JSON using DateParseHandling.None or DateParseHandling.DateTimeOffset, however JsonConvert.DeserializeXmlNode has no overload that allows this setting to be passed in. Thus you will need to create an extension method with the necessary argument:

public static partial class JsonExtensions
{
    public static XmlDocument DeserializeXmlNode(string json, DateParseHandling dateParseHandling, 
                                                 string deserializeRootElementName = null, bool writeArrayAttribute = false, bool encodeSpecialCharacters = false)
    {
        var settings = new JsonSerializerSettings
        {
            Converters = 
            { 
                new Newtonsoft.Json.Converters.XmlNodeConverter() 
                {
                    DeserializeRootElementName = deserializeRootElementName,
                    WriteArrayAttribute = writeArrayAttribute,
                    EncodeSpecialCharacters = encodeSpecialCharacters
                } 
            },
            DateParseHandling = dateParseHandling,
        };

        return JsonConvert.DeserializeObject<XmlDocument>(json, settings);
    }
}

Then use it as follows:

var xmlDoc = JsonExtensions.DeserializeXmlNode(jsonString, DateParseHandling.None);

Note that both DateParseHandling.None and DateParseHandling.DateTimeOffset meet your needs, as the former disables ISO 8601 date recognition while the latter parses such strings into DateTimeOffset which does support time zone specification.

Incidentally, the equivalent method for those who prefer the newer XDocument is:

public static partial class JsonExtensions
{
    public static XDocument DeserializeXNode(string json, DateParseHandling dateParseHandling, 
                                                 string deserializeRootElementName = null, bool writeArrayAttribute = false, bool encodeSpecialCharacters = false)
    {
        var settings = new JsonSerializerSettings
        {
            Converters = 
            { 
                new Newtonsoft.Json.Converters.XmlNodeConverter() 
                {
                    DeserializeRootElementName = deserializeRootElementName,
                    WriteArrayAttribute = writeArrayAttribute,
                    EncodeSpecialCharacters = encodeSpecialCharacters
                } 
            },
            DateParseHandling = dateParseHandling,
        };

        return JsonConvert.DeserializeObject<XDocument>(json, settings);
    }
}

Demo fiddle here.




回答2:


I would read the node as string and write it as a string. That's the only sure way.

Toy example solution JsonConvert.DefaultSetting

// Setting the default settings is the only way I know to affect settings
// for DeserializeXmlNode, there may be a better way
Newtonsoft.Json.JsonConvert.DefaultSettings = 
    () => new Newtonsoft.Json.JsonSerializerSettings() { 
    DateParseHandling = Newtonsoft.Json.DateParseHandling.None };

Beware! Changing Newtonsoft.Json.JsonConvert.DefaultSettings can affect other parts of your solution!

Test

var json = @"
{
    ""Flight"": {
        ""FlightNumber"": ""747"",
        ""Source"": ""JFK"",
        ""Destination"": ""LAS"",   
        ""Status"": ""ON TIME"",
        ""DepDateTime"": ""2019-10-25T07:00:00-05:00"",
        ""Terminal"": ""2""
    }
}            
";

Newtonsoft.Json.JsonConvert.DefaultSettings = () => new Newtonsoft.Json.JsonSerializerSettings() { DateParseHandling = Newtonsoft.Json.DateParseHandling.None };

System.Xml.XmlDocument xmlDoc = Newtonsoft.Json.JsonConvert.DeserializeXmlNode(json);
Console.WriteLine(xmlDoc.InnerXml);

Output

(...)<DepDateTime>2019-10-25T07:00:00-05:00</DepDateTime><Terminal>2</Terminal></Flight>

Output without setting the settings

(...)<DepDateTime>2019-10-25T22:00:00+10:00</DepDateTime><Terminal>2</Terminal></Flight>


来源:https://stackoverflow.com/questions/58530977/how-to-prevent-date-time-conversion-while-converting-a-json-string-to-xml-do

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!