Megosztás a következőn keresztül:


A DateTime és a DateTimeOffset támogatása a System.Text.Json-ban

A System.Text.Json kódtár az ISO 8601-1:2019 kiterjesztett profilnak megfelelően elemzi és DateTimeOffset írja DateTime és értékeli az értékeket. A konverterek egyéni támogatást nyújtanak a szerializáláshoz és a deszerializáláshoz.JsonSerializer Egyéni támogatást is használhat Utf8JsonReader és Utf8JsonWriter implementálhat.

Az ISO 8601-1:2019 formátum támogatása

A JsonSerializer, Utf8JsonReader, Utf8JsonWriter, és JsonElement az ISO 8601-1:2019 formátum kiterjesztett profiljának megfelelően elemzi és írja DateTime DateTimeOffset és írja be a szövegábrázolásokat. Például: 2019-07-26T16:59:57-05:00.

DateTime és DateTimeOffset az adatok szerializálhatók a következővel JsonSerializer:

using System.Text.Json;

public class Example
{
    private class Product
    {
        public string? Name { get; set; }
        public DateTime ExpiryDate { get; set; }
    }

    public static void Main(string[] args)
    {
        Product p = new Product();
        p.Name = "Banana";
        p.ExpiryDate = new DateTime(2019, 7, 26);

        string json = JsonSerializer.Serialize(p);
        Console.WriteLine(json);
    }
}

// The example displays the following output:
// {"Name":"Banana","ExpiryDate":"2019-07-26T00:00:00"}

DateTime és DateTimeOffset deszerializálható a következővel JsonSerializeris:

using System.Text.Json;

public class Example
{
    private class Product
    {
        public string? Name { get; set; }
        public DateTime ExpiryDate { get; set; }
    }

    public static void Main(string[] args)
    {
        string json = @"{""Name"":""Banana"",""ExpiryDate"":""2019-07-26T00:00:00""}";
        Product p = JsonSerializer.Deserialize<Product>(json)!;
        Console.WriteLine(p.Name);
        Console.WriteLine(p.ExpiryDate);
    }
}

// The example displays output similar to the following:
// Banana
// 7/26/2019 12:00:00 AM

Az alapértelmezett beállításokkal a bemeneti DateTime és DateTimeOffset szöveges ábrázolásoknak meg kell felelniük a kiterjesztett ISO 8601-1:2019-profilnak. Ha megkísérli deszerializálni a profilnak nem megfelelő reprezentációkat, a következőt fogja eredményezni JsonSerializer JsonException:

using System.Text.Json;

public class Example
{
    private class Product
    {
        public string? Name { get; set; }
        public DateTime ExpiryDate { get; set; }
    }

    public static void Main(string[] args)
    {
        string json = @"{""Name"":""Banana"",""ExpiryDate"":""26/07/2019""}";
        try
        {
            Product _ = JsonSerializer.Deserialize<Product>(json)!;
        }
        catch (JsonException e)
        {
            Console.WriteLine(e.Message);
        }
    }
}

// The example displays the following output:
// The JSON value could not be converted to System.DateTime. Path: $.ExpiryDate | LineNumber: 0 | BytePositionInLine: 42.

Ez JsonDocument strukturált hozzáférést biztosít egy JSON-hasznos adat tartalmához, beleértve DateTime a reprezentációkat is DateTimeOffset . Az alábbi példa bemutatja, hogyan számítható ki a hétfői átlaghőmérséklet egy hőmérséklet-gyűjteményből:

using System.Text.Json;

public class Example
{
    private static double ComputeAverageTemperatures(string json)
    {
        JsonDocumentOptions options = new JsonDocumentOptions
        {
            AllowTrailingCommas = true
        };

        using (JsonDocument document = JsonDocument.Parse(json, options))
        {
            int sumOfAllTemperatures = 0;
            int count = 0;

            foreach (JsonElement element in document.RootElement.EnumerateArray())
            {
                DateTimeOffset date = element.GetProperty("date").GetDateTimeOffset();

                if (date.DayOfWeek == DayOfWeek.Monday)
                {
                    int temp = element.GetProperty("temp").GetInt32();
                    sumOfAllTemperatures += temp;
                    count++;
                }
            }

            double averageTemp = (double)sumOfAllTemperatures / count;
            return averageTemp;
        }
    }

    public static void Main(string[] args)
    {
        string json =
                @"[" +
                    @"{" +
                        @"""date"": ""2013-01-07T00:00:00Z""," +
                        @"""temp"": 23," +
                    @"}," +
                    @"{" +
                        @"""date"": ""2013-01-08T00:00:00Z""," +
                        @"""temp"": 28," +
                    @"}," +
                    @"{" +
                        @"""date"": ""2013-01-14T00:00:00Z""," +
                        @"""temp"": 8," +
                    @"}," +
                @"]";

        Console.WriteLine(ComputeAverageTemperatures(json));
    }
}

// The example displays the following output:
// 15.5

Ha megkísérli kiszámítani az átlagos hőmérsékletet egy hasznos adat alapján, nem megfelelő DateTime ábrázolásokkal, a következőt fogja eredményezni JsonDocument FormatException:

using System.Text.Json;

public class Example
{
    private static double ComputeAverageTemperatures(string json)
    {
        JsonDocumentOptions options = new JsonDocumentOptions
        {
            AllowTrailingCommas = true
        };

        using (JsonDocument document = JsonDocument.Parse(json, options))
        {
            int sumOfAllTemperatures = 0;
            int count = 0;

            foreach (JsonElement element in document.RootElement.EnumerateArray())
            {
                DateTimeOffset date = element.GetProperty("date").GetDateTimeOffset();

                if (date.DayOfWeek == DayOfWeek.Monday)
                {
                    int temp = element.GetProperty("temp").GetInt32();
                    sumOfAllTemperatures += temp;
                    count++;
                }
            }

            double averageTemp = (double)sumOfAllTemperatures / count;
            return averageTemp;
        }
    }

    public static void Main(string[] args)
    {
        // Computing the average temperatures will fail because the DateTimeOffset
        // values in the payload do not conform to the extended ISO 8601-1:2019 profile.
        string json =
                @"[" +
                    @"{" +
                        @"""date"": ""2013/01/07 00:00:00Z""," +
                        @"""temp"": 23," +
                    @"}," +
                    @"{" +
                        @"""date"": ""2013/01/08 00:00:00Z""," +
                        @"""temp"": 28," +
                    @"}," +
                    @"{" +
                        @"""date"": ""2013/01/14 00:00:00Z""," +
                        @"""temp"": 8," +
                    @"}," +
                @"]";

        Console.WriteLine(ComputeAverageTemperatures(json));
    }
}

// The example displays the following output:
// Unhandled exception.System.FormatException: One of the identified items was in an invalid format.
//    at System.Text.Json.JsonElement.GetDateTimeOffset()

Az alacsonyabb szintű Utf8JsonWriter írások DateTime és DateTimeOffset adatok:

using System.Text;
using System.Text.Json;

public class Example
{
    public static void Main(string[] args)
    {
        JsonWriterOptions options = new JsonWriterOptions
        {
            Indented = true
        };

        using (MemoryStream stream = new MemoryStream())
        {
            using (Utf8JsonWriter writer = new Utf8JsonWriter(stream, options))
            {
                writer.WriteStartObject();
                writer.WriteString("date", DateTimeOffset.UtcNow);
                writer.WriteNumber("temp", 42);
                writer.WriteEndObject();
            }

            string json = Encoding.UTF8.GetString(stream.ToArray());
            Console.WriteLine(json);
        }
    }
}

// The example output similar to the following:
// {
//     "date": "2019-07-26T00:00:00+00:00",
//     "temp": 42
// }

Utf8JsonReader elemzések DateTime és DateTimeOffset adatok:

using System.Text;
using System.Text.Json;

public class Example
{
    public static void Main(string[] args)
    {
        byte[] utf8Data = Encoding.UTF8.GetBytes(@"""2019-07-26T00:00:00""");

        Utf8JsonReader json = new Utf8JsonReader(utf8Data);
        while (json.Read())
        {
            if (json.TokenType == JsonTokenType.String)
            {
                Console.WriteLine(json.TryGetDateTime(out DateTime datetime));
                Console.WriteLine(datetime);
                Console.WriteLine(json.GetDateTime());
            }
        }
    }
}

// The example displays output similar to the following:
// True
// 7/26/2019 12:00:00 AM
// 7/26/2019 12:00:00 AM

A nem megfelelő formátumok olvasásának megkísérlése Utf8JsonReader a következőt eredményezi FormatException:

using System.Text;
using System.Text.Json;

public class Example
{
    public static void Main(string[] args)
    {
        byte[] utf8Data = Encoding.UTF8.GetBytes(@"""2019/07/26 00:00:00""");

        Utf8JsonReader json = new Utf8JsonReader(utf8Data);
        while (json.Read())
        {
            if (json.TokenType == JsonTokenType.String)
            {
                Console.WriteLine(json.TryGetDateTime(out DateTime datetime));
                Console.WriteLine(datetime);

                DateTime _ = json.GetDateTime();
            }
        }
    }
}

// The example displays the following output:
// False
// 1/1/0001 12:00:00 AM
// Unhandled exception. System.FormatException: The JSON value is not in a supported DateTime format.
//     at System.Text.Json.Utf8JsonReader.GetDateTime()

DateOnly és TimeOnly tulajdonságok szerializálása

A .NET 7+ támogatja a szerializálást és System.Text.Json a deszerializálást DateOnly és TimeOnly a típusokat. Vegye figyelembe a következő objektumot:

sealed file record Appointment(
    Guid Id,
    string Description,
    DateOnly Date,
    TimeOnly StartTime,
    TimeOnly EndTime);

Az alábbi példa szerializál egy Appointment objektumot, megjeleníti az eredményül kapott JSON-t, majd deszerializálja azt egy új típusú példányba Appointment . Végül összehasonlítja az eredeti és az újonnan deszerializált példányokat az egyenlőség szempontjából, és az eredmények a konzolra kerülnek:

Appointment originalAppointment = new(
    Id: Guid.NewGuid(),
    Description: "Take dog to veterinarian.",
    Date: new DateOnly(2002, 1, 13),
    StartTime: new TimeOnly(5,15),
    EndTime: new TimeOnly(5, 45));
string serialized = JsonSerializer.Serialize(originalAppointment);

Console.WriteLine($"Resulting JSON: {serialized}");

Appointment deserializedAppointment =
    JsonSerializer.Deserialize<Appointment>(serialized)!;

bool valuesAreTheSame = originalAppointment == deserializedAppointment;
Console.WriteLine($"""
    Original record has the same values as the deserialized record: {valuesAreTheSame}
    """);

A fenti kód a következőket végzi el:

  • A rendszer létrehoz egy Appointment objektumot, és hozzá van rendelve a appointment változóhoz.
  • A appointment példány JSON-ra van szerializálva a .JsonSerializer.Serialize
  • Az eredményként kapott JSON-t a rendszer a konzolra írja.
  • A JSON vissza lesz deszerializálva a típus új példányába a Appointment használatával JsonSerializer.Deserialize.
  • A rendszer összehasonlítja az eredeti és az újonnan deszerializált példányokat az egyenlőség szempontjából.
  • Az összehasonlítás eredménye a konzolra lesz írva.

Egyéni támogatás és DateTimeDateTimeOffset

Használatkor JsonSerializer

Ha azt szeretné, hogy a szerializáló egyéni elemzést vagy formázást végezzen, egyéni konvertereket implementálhat. Íme néhány példa:

DateTime(Eltolás). Elemzés és DateTime(Eltolás). ToString

Ha nem tudja meghatározni a bemeneti DateTime vagy DateTimeOffset szöveges ábrázolások formátumát, használhatja a metódust a DateTime(Offset).Parse konverter olvasási logikájában. Ez a módszer lehetővé teszi a használatát. A NET széles körű támogatása különböző DateTime és DateTimeOffset szöveges formátumok elemzéséhez, beleértve a nem ISO 8601 sztringeket és az ISO 8601 formátumokat, amelyek nem felelnek meg a kiterjesztett ISO 8601-1:2019 profilnak. Ez a megközelítés kevésbé teljesít, mint a szerializáló natív implementációjának használata.

Szerializáláshoz használhatja a metódust a DateTime(Offset).ToString konverter írási logikájában. Ez a módszer lehetővé teszi az írást DateTime és DateTimeOffset az értékeket a szokásos dátum- és időformátumok, valamint az egyéni dátum- és időformátumok használatával. Ez a megközelítés kevésbé teljesít, mint a szerializáló natív implementációjának használata.

using System.Diagnostics;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;

namespace DateTimeConverterExamples;

public class DateTimeConverterUsingDateTimeParse : JsonConverter<DateTime>
{
    public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        Debug.Assert(typeToConvert == typeof(DateTime));
        return DateTime.Parse(reader.GetString() ?? string.Empty);
    }

    public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString());
    }
}

class Program
{
    private static void ParseDateTimeWithDefaultOptions()
    {
        DateTime _ = JsonSerializer.Deserialize<DateTime>(@"""04-10-2008 6:30 AM""");
    }

    private static void FormatDateTimeWithDefaultOptions()
    {
        Console.WriteLine(JsonSerializer.Serialize(DateTime.Parse("04-10-2008 6:30 AM -4")));
    }

    private static void ProcessDateTimeWithCustomConverter()
    {
        JsonSerializerOptions options = new JsonSerializerOptions();
        options.Converters.Add(new DateTimeConverterUsingDateTimeParse());

        string testDateTimeStr = "04-10-2008 6:30 AM";
        string testDateTimeJson = @"""" + testDateTimeStr + @"""";

        DateTime resultDateTime = JsonSerializer.Deserialize<DateTime>(testDateTimeJson, options);
        Console.WriteLine(resultDateTime);

        string resultDateTimeJson = JsonSerializer.Serialize(DateTime.Parse(testDateTimeStr), options);
        Console.WriteLine(Regex.Unescape(resultDateTimeJson));
    }

    static void Main(string[] args)
    {
        // Parsing non-compliant format as DateTime fails by default.
        try
        {
            ParseDateTimeWithDefaultOptions();
        }
        catch (JsonException e)
        {
            Console.WriteLine(e.Message);
        }

        // Formatting with default options prints according to extended ISO 8601 profile.
        FormatDateTimeWithDefaultOptions();

        // Using converters gives you control over the serializers parsing and formatting.
        ProcessDateTimeWithCustomConverter();
    }
}

// The example displays output similar to the following:
// The JSON value could not be converted to System.DateTime. Path: $ | LineNumber: 0 | BytePositionInLine: 20.
// "2008-04-10T06:30:00-04:00"
// 4/10/2008 6:30:00 AM
// "4/10/2008 6:30:00 AM"

Feljegyzés

A implementáláskor JsonConverter<T>T DateTimea paraméter mindig az typeToConvert lesz typeof(DateTime). Ez a paraméter hasznos a polimorf esetek kezeléséhez, és általános eszközök typeof(T) használata esetén a teljesítmény szempontjából.

Utf8Parser és Utf8Formatter

Gyors UTF-8-alapú elemzési és formázási módszereket használhat a konverterlogikában, ha a bemeneti DateTime vagy DateTimeOffset szöveges reprezentációk megfelelnek az "R", az "l", az "O" vagy a "G" szabványos dátum- és időformátum-sztringek egyikének, vagy az alábbi formátumok egyikének megfelelően szeretne írni. Ez a megközelítés sokkal gyorsabb, mint a használata DateTime(Offset).Parse és DateTime(Offset).ToString.

Az alábbi példa egy egyéni konvertert mutat be, amely szerializálja és deszerializálja az értékeket DateTime az "R" standard formátum szerint:

using System.Buffers;
using System.Buffers.Text;
using System.Diagnostics;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace DateTimeConverterExamples;

// This converter reads and writes DateTime values according to the "R" standard format specifier:
// https://learn.microsoft.com/dotnet/standard/base-types/standard-date-and-time-format-strings#the-rfc1123-r-r-format-specifier.
public class DateTimeConverterForCustomStandardFormatR : JsonConverter<DateTime>
{
    public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        Debug.Assert(typeToConvert == typeof(DateTime));

        if (Utf8Parser.TryParse(reader.ValueSpan, out DateTime value, out _, 'R'))
        {
            return value;
        }

        throw new FormatException();
    }

    public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
    {
        // The "R" standard format will always be 29 bytes.
        Span<byte> utf8Date = new byte[29];

        bool result = Utf8Formatter.TryFormat(value, utf8Date, out _, new StandardFormat('R'));
        Debug.Assert(result);

        writer.WriteStringValue(utf8Date);
    }
}

class Program
{
    private static void ParseDateTimeWithDefaultOptions()
    {
        DateTime _ = JsonSerializer.Deserialize<DateTime>(@"""Thu, 25 Jul 2019 13:36:07 GMT""");
    }

    private static void ProcessDateTimeWithCustomConverter()
    {
        JsonSerializerOptions options = new JsonSerializerOptions();
        options.Converters.Add(new DateTimeConverterForCustomStandardFormatR());

        string testDateTimeStr = "Thu, 25 Jul 2019 13:36:07 GMT";
        string testDateTimeJson = @"""" + testDateTimeStr + @"""";

        DateTime resultDateTime = JsonSerializer.Deserialize<DateTime>(testDateTimeJson, options);
        Console.WriteLine(resultDateTime);

        Console.WriteLine(JsonSerializer.Serialize(DateTime.Parse(testDateTimeStr), options));
    }

    static void Main(string[] args)
    {
        // Parsing non-compliant format as DateTime fails by default.
        try
        {
            ParseDateTimeWithDefaultOptions();
        }
        catch (JsonException e)
        {
            Console.WriteLine(e.Message);
        }

        // Using converters gives you control over the serializers parsing and formatting.
        ProcessDateTimeWithCustomConverter();
    }
}

// The example displays output similar to the following:
// The JSON value could not be converted to System.DateTime.Path: $ | LineNumber: 0 | BytePositionInLine: 31.
// 7/25/2019 1:36:07 PM
// "Thu, 25 Jul 2019 09:36:07 GMT"

Feljegyzés

Az "R" standard formátum mindig 29 karakter hosszú lesz.

Az "l" (kisbetűs "L") formátum nincs dokumentálva a többi szabványos dátum- és időformátum-sztringgel, mert csak a típusok és Utf8Formatter a Utf8Parser típusok támogatják. A formátum kisbetűs RFC 1123 (az "R" formátum kisbetűs verziója). Például: "thu, 25 jul 2019 06:36:07 gmt".

DateTime(Eltolás) használata. Elemzés tartalékként

Ha általában arra számít, hogy a bemenet DateTime vagy DateTimeOffset az adatok megfelelnek a kiterjesztett ISO 8601-1:2019-profilnak, használhatja a szerializáló natív elemzési logikáját. Tartalék mechanizmust is implementálhat. Az alábbi példa azt mutatja be, hogy miután nem sikerült elemezni egy DateTime szöveges ábrázolás használatát TryGetDateTime(DateTime), a konverter sikeresen elemzi az adatokat a következő használatával Parse(String):

using System.Diagnostics;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;

namespace DateTimeConverterExamples;

public class DateTimeConverterUsingDateTimeParseAsFallback : JsonConverter<DateTime>
{
    public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        Debug.Assert(typeToConvert == typeof(DateTime));

        if (!reader.TryGetDateTime(out DateTime value))
        {
            value = DateTime.Parse(reader.GetString()!);
        }

        return value;
    }

    public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString("dd/MM/yyyy"));
    }
}

class Program
{
    private static void ParseDateTimeWithDefaultOptions()
    {
        DateTime _ = JsonSerializer.Deserialize<DateTime>(@"""2019-07-16 16:45:27.4937872+00:00""");
    }

    private static void ProcessDateTimeWithCustomConverter()
    {
        JsonSerializerOptions options = new JsonSerializerOptions();
        options.Converters.Add(new DateTimeConverterUsingDateTimeParseAsFallback());

        string testDateTimeStr = "2019-07-16 16:45:27.4937872+00:00";
        string testDateTimeJson = @"""" + testDateTimeStr + @"""";

        DateTime resultDateTime = JsonSerializer.Deserialize<DateTime>(testDateTimeJson, options);
        Console.WriteLine(resultDateTime);

        string resultDateTimeJson = JsonSerializer.Serialize(DateTime.Parse(testDateTimeStr), options);
        Console.WriteLine(Regex.Unescape(resultDateTimeJson));
    }

    static void Main(string[] args)
    {
        // Parsing non-compliant format as DateTime fails by default.
        try
        {
            ParseDateTimeWithDefaultOptions();
        }
        catch (JsonException e)
        {
            Console.WriteLine(e.Message);
        }

        // Using converters gives you control over the serializers parsing and formatting.
        ProcessDateTimeWithCustomConverter();
    }
}

// The example displays output similar to the following:
// The JSON value could not be converted to System.DateTime.Path: $ | LineNumber: 0 | BytePositionInLine: 35.
// 7/16/2019 4:45:27 PM
// "16/07/2019"

Unix-korszak dátumformátumának használata

Az alábbi konverterek időzóna eltolással vagy anélkül kezelik a Unix-korszak formátumát (például /Date(1590863400000-0700)/ vagy /Date(1590863400000)/):

sealed class UnixEpochDateTimeOffsetConverter : JsonConverter<DateTimeOffset>
{
    static readonly DateTimeOffset s_epoch = new(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
    static readonly Regex s_regex = new("^/Date\\(([+-]*\\d+)([+-])(\\d{2})(\\d{2})\\)/$", RegexOptions.CultureInvariant);

    public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        string formatted = reader.GetString()!;
        Match match = s_regex.Match(formatted);

        if (
                !match.Success
                || !long.TryParse(match.Groups[1].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out long unixTime)
                || !int.TryParse(match.Groups[3].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out int hours)
                || !int.TryParse(match.Groups[4].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out int minutes))
        {
            throw new JsonException();
        }

        int sign = match.Groups[2].Value[0] == '+' ? 1 : -1;
        TimeSpan utcOffset = new(hours * sign, minutes * sign, 0);

        return s_epoch.AddMilliseconds(unixTime).ToOffset(utcOffset);
    }

    public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options)
    {
        long unixTime = Convert.ToInt64((value - s_epoch).TotalMilliseconds);
        TimeSpan utcOffset = value.Offset;

        string formatted = string.Create(CultureInfo.InvariantCulture, $"/Date({unixTime}{(utcOffset >= TimeSpan.Zero ? "+" : "-")}{utcOffset:hhmm})/");

        writer.WriteStringValue(formatted);
    }
}
sealed class UnixEpochDateTimeConverter : JsonConverter<DateTime>
{
    static readonly DateTime s_epoch = new(1970, 1, 1, 0, 0, 0);
    static readonly Regex s_regex = new("^/Date\\(([+-]*\\d+)\\)/$", RegexOptions.CultureInvariant);

    public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        string formatted = reader.GetString()!;
        Match match = s_regex.Match(formatted);

        if (
                !match.Success
                || !long.TryParse(match.Groups[1].Value, System.Globalization.NumberStyles.Integer, CultureInfo.InvariantCulture, out long unixTime))
        {
            throw new JsonException();
        }

        return s_epoch.AddMilliseconds(unixTime);
    }

    public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
    {
        long unixTime = Convert.ToInt64((value - s_epoch).TotalMilliseconds);

        string formatted = string.Create(CultureInfo.InvariantCulture, $"/Date({unixTime})/");
        writer.WriteStringValue(formatted);
    }
}

Használatkor Utf8JsonWriter

Ha egyéni DateTime vagy DateTimeOffset szöveges ábrázolásokat Utf8JsonWriterszeretne írni, formázhatja az egyéni ábrázolásokat egy String, ReadOnlySpan<Byte>, ReadOnlySpan<Char>vagy JsonEncodedText, majd átadhatja a megfelelőnek Utf8JsonWriter.WriteStringValue vagy Utf8JsonWriter.WriteString metódusnak.

Az alábbi példa bemutatja, hogyan hozható létre egyéni DateTime formátum a metódussal ToString(String, IFormatProvider) , majd hogyan írható meg WriteStringValue(String) :

using System.Globalization;
using System.Text;
using System.Text.Json;

public class Example
{
    public static void Main(string[] args)
    {
        var options = new JsonWriterOptions
        {
            Indented = true
        };

        using (var stream = new MemoryStream())
        {
            using (var writer = new Utf8JsonWriter(stream, options))
            {
                string dateStr = DateTime.UtcNow.ToString("F", CultureInfo.InvariantCulture);

                writer.WriteStartObject();
                writer.WriteString("date", dateStr);
                writer.WriteNumber("temp", 42);
                writer.WriteEndObject();
            }

            string json = Encoding.UTF8.GetString(stream.ToArray());
            Console.WriteLine(json);
        }
    }
}

// The example displays output similar to the following:
// {
//     "date": "Tuesday, 27 August 2019 19:21:44",
//     "temp": 42
// }

Használatkor Utf8JsonReader

Ha egyéni DateTime vagy DateTimeOffset szöveges ábrázolásokat Utf8JsonReaderszeretne olvasni, az aktuális JSON-jogkivonat értékét lekérheti használati GetString() módszerkéntString, majd egyéni logikával elemezheti az értéket.

Az alábbi példa bemutatja, hogyan kérhető le egy egyéni DateTimeOffset szövegábrázolás a módszerrel, majd elemezhető a GetString() következővel ParseExact(String, String, IFormatProvider):

using System.Globalization;
using System.Text;
using System.Text.Json;

public class Example
{
    public static void Main(string[] args)
    {
        byte[] utf8Data = Encoding.UTF8.GetBytes(@"""Friday, 26 July 2019 00:00:00""");

        var json = new Utf8JsonReader(utf8Data);
        while (json.Read())
        {
            if (json.TokenType == JsonTokenType.String)
            {
                string value = json.GetString();
                DateTimeOffset dto = DateTimeOffset.ParseExact(value, "F", CultureInfo.InvariantCulture);
                Console.WriteLine(dto);
            }
        }
    }
}

// The example displays output similar to the following:
// 7/26/2019 12:00:00 AM -04:00

A System.Text.Json kiterjesztett ISO 8601-1:2019-profilja

Dátum- és időösszetevők

A kiterjesztett ISO 8601-1:2019-profil a System.Text.Json következő összetevőket határozza meg a dátum- és időábrázolásokhoz. Ezek az összetevők különböző támogatott részletességi szintek meghatározására szolgálnak elemzéskor, formázáskor DateTime és DateTimeOffset ábrázolásoknál.

Összetevő Formátum Leírás
Year "yyyy" 0001-9999
Month "MM" 01-12
Nap "dd" 01-28, 01-29, 01-30, 01-31 hónap/év alapján.
Óra "HH" 00-23
Minute "mm" 00-59
Second "ss" 00-59
Második tört "FFFFFFF" Legalább egy számjegy, legfeljebb 16 számjegy.
Időeltolódás "K" "Z" vagy "('+'/'-')HH':'mm".
Részleges idő "HH':'mm':'ss[FFFFF]" Idő UTC-eltolás adatai nélkül.
Teljes dátum "yyyy'-'MM'-'dd" Naptár dátuma.
Teljes munkaidő "'Részleges idő'K" A nap UTC-jének vagy a nap helyi időpontjának időeltolása a helyi idő és az UTC között.
Dátum/Idő "'Teljes dátum''T'''Teljes munkaidő'" Naptári dátum és nap időpontja, például 2019-07-26T16:59:57-05:00.

Elemzés támogatása

Az elemzéshez a következő részletességi szintek vannak meghatározva:

  1. "Teljes dátum"

    1. "yyyy'-'MM'-'dd"
  2. "'Teljes dátum''T''Hour'':'Minute'"

    1. "yyyy'-'MM'-'dd'T'HH':'mm"
  3. "'Teljes dátum''T'''Részleges idő'"

    1. "yyyy'-'MM'-'dd'T'HH':'mm':'ss" (A Rendezhető ("s") formátumjelölő)
    2. "yyyy'-'MM'-'dd'T'HH':'mm':'ss'." FFFFFFF"
  4. "'Teljes dátum''T''Time hour''':'Minute'''Time offset'"

    1. "yyyy'-'MM'-'dd'T'HH':'mmZ"
    2. "yyyy'-'MM'-'dd'T'HH':'mm('+'/'-')HH':'mm"
  5. "Dátum idő"

    1. "yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"
    2. "yyyy'-'MM'-'dd'T'HH':'mm':'ss'." FFFFFFFZ"
    3. "yyyy'-'MM'-'dd'T'HH':'mm':'ss('+'/'-')HH':'mm"
    4. "yyyy'-'MM'-'dd'T'HH':'mm':'ss'." FFFFFFF('+'/'-')HH':'mm"

    Ez a részletességi szint megfelel az RFC 3339-nek, amely az ISO 8601 széles körben elterjedt profilja, amelyet a dátum- és időadatok közötti összefüggésekhez használnak. A megvalósításban azonban van néhány korlátozás System.Text.Json .

    • Az RFC 3339 nem határozza meg a tört másodperces számjegyek maximális számát, de azt határozza meg, hogy legalább egy számjegynek követnie kell az időszakot, ha tört-másodperc szakasz van jelen. A megvalósítás System.Text.Json legfeljebb 16 számjegyet tesz lehetővé (más programozási nyelvekkel és keretrendszerekkel való együttműködés támogatására), de csak az első hétet elemzi. A JsonException lesz dobva, ha több mint 16 tört másodperc számjegyek olvasáskor DateTime és DateTimeOffset példányok.
    • Az RFC 3339 lehetővé teszi, hogy a "T" és a "Z" karakter "t" vagy "z" legyen, de lehetővé teszi az alkalmazások számára, hogy csak a nagybetűs változatokra korlátozzák a támogatást. A megvalósításhoz System.Text.Json "T" és "Z" értékre van szükség. A JsonException lesz dobva, ha a bemeneti hasznos adatok "t" vagy "z" értéket tartalmaznak olvasáskor DateTime és DateTimeOffset példányokban.
    • Az RFC 3339 azt határozza meg, hogy a dátum- és időszakaszokat "T" választja el egymástól, de lehetővé teszi az alkalmazások számára, hogy szóközzel (" ") elválasztsák őket. System.Text.Json a dátum- és időszakaszokat "T" betűvel kell elválasztani. A JsonException lesz dobva, ha a bemeneti hasznos adatok szóközt (" ") tartalmaznak olvasáskor DateTime és DateTimeOffset példányokban.

Ha másodpercekig tizedes törtek vannak, legalább egy számjegynek kell lennie. 2019-07-26T00:00:00. nem engedélyezett. Bár legfeljebb 16 törtjegy engedélyezett, csak az első hét van elemezve. Bármi, ami azon túl nulla. Például úgy lesz elemezve, 2019-07-26T00:00:00.1234567890 mintha az 2019-07-26T00:00:00.1234567lenne. Ez a megközelítés fenntartja a DateTime végrehajtással való kompatibilitást, amely csak erre az állásfoglalásra korlátozódik.

A szökő másodpercek nem támogatottak.

Formázás támogatása

A formázáshoz a következő részletességi szintek vannak meghatározva:

  1. "'Teljes dátum''T'''Részleges idő'"

    1. "yyyy'-'MM'-'dd'T'HH':'mm':'ss" (A Rendezhető ("s") formátumjelölő)

      Tört másodpercek és eltolások nélkül formázható DateTime .

    2. "yyyy'-'MM'-'dd'T'HH':'mm':'ss'." FFFFFFF"

      Tört másodpercben, de eltolási információ nélkül formázható DateTime .

  2. "Dátum idő"

    1. "yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"

      Tört másodperc nélküli, de UTC-eltolású formázásra DateTime szolgál.

    2. "yyyy'-'MM'-'dd'T'HH':'mm':'ss'." FFFFFFFZ"

      Tört másodperces és UTC-eltolású formázásra DateTime szolgál.

    3. "yyyy'-'MM'-'dd'T'HH':'mm':'ss('+'/'-')HH':'mm"

      Tört másodpercek formázására DateTime DateTimeOffset szolgál, de helyi eltolással.

    4. "yyyy'-'MM'-'dd'T'HH':'mm':'ss'." FFFFFFF('+'/'-')HH':'mm"

      Tört másodpercben és DateTimeOffset helyi eltolással formázhatóDateTime.

    Ez a részletességi szint megfelel az RFC 3339-nek.

Ha egy DateTime vagy DateTimeOffset egy példány egész útformátumú ábrázolása a tört másodpercben záró nullákat tartalmaz, akkor JsonSerializer Utf8JsonWriter a példányt nullák nélkül formázza és formázza. Például egy DateTime olyan példány, amelynek az oda-vissza formátuma a 2019-04-24T14:50:17.1010000Zkövetkező lesz: 2019-04-24T14:50:17.101Z JsonSerializer és Utf8JsonWriter.

Ha egy DateTime vagy DateTimeOffset példány teljes trip formátumú ábrázolása a tört másodpercben minden nullával rendelkezik, akkor JsonSerializer Utf8JsonWriter a példányt tört másodpercek nélkül formázza és formázza. Például egy DateTime olyan példány, amelynek az oda-vissza formátuma a 2019-04-24T14:50:17.0000000+02:00következő lesz: 2019-04-24T14:50:17+02:00 JsonSerializer és Utf8JsonWriter.

A tört másodperces számjegyekben lévő nullák csonkolása lehetővé teszi a legkisebb kimenetet, amely ahhoz szükséges, hogy meg lehessen őrizni a kerek utazással kapcsolatos információkat.

Legfeljebb hét tört másodperces számjegy íródik. Ez a maximum összhangban van a DateTime megvalósítással, amely csak erre az állásfoglalásra korlátozódik.