1

我想将 JSON 响应转换为等效的 XML 文档,但在这样做的同时,我还想保留当前日期和时间格式以及偏移量,例如 JSON 中的 DateTime 为“2019-10-25T07:00:00-05: 00" 并且在转换后我希望它保持不变。但是转换成 XML 后,DateTime 值变成了“2019-10-25T08:00:00-04:00”

我试图在 Microsoft 文档中搜索它,但我没有找到以下问题的答案:

  1. 如何确定给定日期时间字符串的时区(例如,“2019-10-25T07:00:00-05:00”)?
  2. 如何将日期时间字符串(例如,“2019-10-25T08:00:00-04:00”)转换为所需时区的日期时间(例如,转换为“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);

输入 JSON 字符串:

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

预期的:

<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>

实际的:

<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>
4

2 回答 2

2

您的问题是 Json.NET 的自动DateTime识别识别该字符串"2019-10-25T07:00:00-05:00"是有效的ISO 8601日期和时间并将其解析为DateTime-- 不幸的是不支持时区规范。因此,在反序列化过程中,该值会(正确地)转换为计算机上的本地时区,并随后在 XML 中格式化。

为了防止这种情况,您需要使用DateParseHandling.NoneorDateParseHandling.DateTimeOffset解析 JSON ,但是JsonConvert.DeserializeXmlNode没有允许传入此设置的重载。因此,您需要创建一个带有必要参数的扩展方法:

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);
    }
}

然后按如下方式使用它:

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

请注意,两者都DateParseHandling.None满足DateParseHandling.DateTimeOffset您的需求,因为前者禁用 ISO 8601 日期识别,而后者将此类字符串解析为DateTimeOffset支持时区规范的字符串。

顺便说一句,对于那些喜欢更新的人来说,等效的方法XDocument是:

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);
    }
}

演示小提琴在这里

于 2019-10-23T21:58:12.393 回答
0

我会将节点读取为字符串并将其写入字符串。这是唯一确定的方法。

玩具示例解决方案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 };

谨防!更改Newtonsoft.Json.JsonConvert.DefaultSettings可能会影响解决方案的其他部分!

测试

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);

输出

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

无需设置即可输出

(...)<DepDateTime>2019-10-25T22:00:00+10:00</DepDateTime><Terminal>2</Terminal></Flight>
于 2019-10-23T21:14:47.737 回答