Как предотвратить преобразование даты и времени при преобразовании строки json в документ XML - PullRequest
1 голос
/ 24 октября 2019

Я хочу преобразовать ответ JSON в эквивалентный XML-документ, но при этом я также хочу сохранить текущий формат даты и времени вместе со смещением, например, DateTime в JSON: «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>

Ответы [ 2 ]

1 голос
/ 24 октября 2019

Ваша проблема заключается в том, что автоматическое DateTime распознавание в Json.NET распознает, что строка "2019-10-25T07:00:00-05:00" является действительной ISO 8601 датой и временем, и анализирует ее как DateTime - который, к сожалению, не поддерживает спецификацию часового пояса. Таким образом, значение преобразуется (корректно) в местный часовой пояс на вашем компьютере во время десериализации и впоследствии форматируется как таковой в XML.

Чтобы предотвратить это, вам необходимо проанализировать JSON с помощью DateParseHandling.None илиDateParseHandling.DateTimeOffset, однако 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);
    }
}

Демоскрипка здесь .

0 голосов
/ 24 октября 2019

Я бы прочитал узел как строку и записал бы ее как строку. Это единственный верный путь.

Пример игрушечного решения 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>
...