_ããããã§ã«ã©ããã§çããããŠããå Žåã¯ãè©«ã³ããŸããããããç§ã®æ€çŽ¢èœåã§ããå Žåã¯å€±æããŸããã_
æ¢åã®æ¬çªã¢ããªã±ãŒã·ã§ã³ã³ãŒãã䜿çšããŠ3.0ã®ãã¬ãã¥ãŒ6ãè©ŠããŠããŸããããã¹ãããçããåé¡ã®1ã€ã¯ãAPIã³ã³ãã©ã¯ãã§äœ¿çšããæ¢åã®ãªããžã§ã¯ãã®äžéšãTimeSpan
ããããã£ã䜿çšããŠããããšã§ããå€ãããã¯æååãšããŠè¡šãããŸãã
æ°ããSystem.Text.JsonAPIã®3.0ã§TimeSpan
ããããã£ã®ãµããŒããèšç»ãããŠããŸããïŒ
ããã§ãªãå Žåã¯ã9æããåã«ãªãã¡ã¯ã¿ãªã³ã°ãè¡ã£ãŠæååã«å€æŽããæ°ããã·ãªã¢ã©ã€ã¶ãŒã䜿çšã§ããããã«ããããšãéç¥ããŸããèšç»ãããŠããããŸã å®è£ ãããŠããªãå Žåã¯ãåŸã®ãã¬ãã¥ãŒãåŸ ã€å¿ èŠããããŸãããããæ©èœãããããã«ã
以äžã¯ãæ¢åã®JSON .NETã³ãŒããšæ¯èŒããŠã TimeSpan
åŠçã®å€±æã瀺ãæå°éã®åçŸãŠããããã¹ãã§ãã
using System;
using System.Text.Json.Serialization;
using Xunit;
using JsonConvert = Newtonsoft.Json.JsonConvert;
using JsonSerializer = System.Text.Json.Serialization.JsonSerializer;
namespace JsonSerializerTimeSpanNotSupportedException
{
public static class Repro
{
[Fact]
public static void Can_Deserialize_Object_With_SystemTextJson()
{
// Arrange
string json = "{\"child\":{\"value\":\"00:10:00\"}}";
// Act (fails in preview 6, throws: System.Text.Json.JsonException : The JSON value could not be converted to System.TimeSpan. Path: $.child.value | LineNumber: 0 | BytePositionInLine: 28.)
var actual = JsonSerializer.Parse<Parent>(json, new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
// Assert
Assert.NotNull(actual);
Assert.NotNull(actual.Child);
Assert.Equal(TimeSpan.FromMinutes(10), actual.Child.Value);
}
[Fact]
public static void Can_Deserialize_Object_With_NewtonsoftJson()
{
// Arrange
string json = "{\"child\":{\"value\":\"00:10:00\"}}";
var actual = JsonConvert.DeserializeObject<Parent>(json);
// Assert
Assert.NotNull(actual);
Assert.NotNull(actual.Child);
Assert.Equal(TimeSpan.FromMinutes(10), actual.Child.Value);
}
private sealed class Parent
{
public Child Child { get; set; }
}
private sealed class Child
{
public TimeSpan Value { get; set; }
}
}
}
çŸåšã TimeSpan
ããµããŒãããäºå®ã¯ãªããå°æ¥è¿œå ãããäºå®ã§ããã調æ»ãè¡ã£ãŠãã©ã®çšåºŠã®äœæ¥ãå¿
èŠãã確èªã§ããŸãã ãŸãã¯ãåé¿çãšããŠTimeSpan
ããµããŒãããç¬èªã®JsonConverter
ãäœæããããšãã§ããŸãã æ¥é±ã®çµãããŸã§ã«æŽæ°ãè¡ããŸãã ããããšãã
è¿œå ããå Žåã¯ã TimeSpan
APIãreader / writer / JsonElementã«è¿œå ããå¿
èŠããããŸããããã¯ãAPIã¬ãã¥ãŒãè¡ãå¿
èŠããããŸãã
ããããšã-ã«ã¹ã¿ã ã³ã³ããŒã¿ãŒã¯ã3.0çšã®ã¢ããªã§åäœãããã®ã«ååç°¡åãªæ¹æ³ã§ããããŸãã ãããã®æ©èœã¯ãã¬ãã¥ãŒ7ã§åºè·ãããäºå®ã§ããïŒ
ã¯ããã«ã¹ã¿ã ã³ã³ããŒã¿ãŒã®ãµããŒãã¯çŸåšãã¹ã¿ãŒã«ããããããã¬ãã¥ãŒ7ã«ãªããŸãã
ãã ããTimeSpanã¯äžè¬çãªBCLã¿ã€ãã§ãããããããã©ã«ãã®ã³ã³ããŒã¿ãŒãæäŸããå¿ èŠããããŸãã
ä»æ¥ãããã¬ãã¥ãŒããŸããïŒ
- æéã®æšæºãšã³ã³ãŒãã£ã³ã°ããããã©ããã¯äžæã§ãã
æéã®æšæºãšã³ã³ãŒãã£ã³ã°ã¯ã XMLãTimeSpan
ãè¡šãããã«äœ¿çšãããã®ã§ãããããã§ã«XmlConvert
ãšXsdDuration
å®è£
ãããŠããŸãã
ããŠãééããªãã TimeSpan
èªäœãISO8601æéãã©ãŒãããã®è§£æãšãã©ãŒãããããµããŒãããã¯ãã§ãã ãã¶ããæåã®ã¹ããããšããŠã DateTime[Offset]
ã®ã©ãŠã³ãããªããïŒ "O"ã "o"ïŒåœ¢åŒæå®åã«äŒŒããæ°ããæšæºã®TimeSpan
圢åŒæååãè¿œå ããæ¹ãããã§ããããã ãã®åŸã«ã³ã³ããŒã¿ãŒãè¿œå ããã®ã¯æ¬åœã«ç°¡åã§ãã
ããã«ãããAspNetCoreãAPIã§TimeSpan
ã¿ã€ããè¿ãæ¹æ³ã®ããã©ã«ãã®åäœãå€æŽãããŸãããdotnet/ AspnetCoreïŒ11724ãåç
§ããŠãã ããã ããã¯é倧ãªå€æŽã§ããå¯èœæ§ããããŸãã
æãç°¡åãªè§£æ±ºçã¯ãã«ã¹ã¿ã ã³ã³ããŒã¿ãŒãäœæããããšã§ãã
public class TimeSpanConverter : JsonConverter<TimeSpan>
{
public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return TimeSpan.Parse(reader.GetString());
}
public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}
}
顧客ã®èšŒæ ã«ã€ããŠè©±ãïŒTimeSpanã®ãœãããŠã§ã¢éçºãµããŒãã¯éââåžžã«å¿ èŠã§ãã
ä»æ¥ãã¢ããªã.NET Core3.0ã«ç§»æ€ããããšã«ééããŸããã ããã¯ééãããŠãããããMicrosoftããã€ãã£ããµããŒããè¿œå ããäºå®ããªãããšãæå³ããŸããïŒ @khellangã®ã³ã¡ã³ãã¯ãã©ããã®ããŒããããã«ããã¹ãã ãšããç§ã«ã¯ããªã説åŸåã®ããè°è«ã®ããã§ã...
è¿œå ã®è³ªåã«åºã¥ããŠ5.0ã§åéããŸãã Newtonsoftãšã®äºææ§ãèæ ®ããå¿ èŠããããŸãããISO8601ã®æéãããããæè¯ã®è¡šçŸã§ãã
ä»æ¥ããã®åé¡ã«ééããŸããã ããã©ã«ãã®åäœã¯ä»¥åã®åäœãããæªãããŸã£ããäºæããŠããŸããã§ããã ISO8601ã䜿çšããããNewtonsoftãšäºææ§ãæãããããšã§ãä¿®æ£ããå¿ èŠããããŸãã
ããã©ã«ãã®åäœã¯ä»¥åã®åäœãããæªãããŸã£ããäºæããŠããŸããã§ããã
@mfeingolã©ã®ãããªæ¯ãèãã§ããïŒ ããã¯åã«å€±æãããšããããšã§ããïŒ
ISO8601ã䜿çšããããNewtonsoftãšäºææ§ãæãããããšã§ãä¿®æ£ããå¿ èŠããããŸãã
åè¿°ã®åé¿ç@rezabayestehãè¿œå ããã®ã¯æ¬åœã«ç°¡åã§ãã
@khellang ïŒæ¯èŒçããã©ãªASP.NET Coreãããžã§ã¯ãã§èŠ³å¯ããã®ã¯ã Timespan?
ãHasValue
ãã£ãŒã«ããšããŠã·ãªã¢ã«åãã次ã«TimeSpanæ§é äœã®åããããã£ãã·ãªã¢ã«åããããšã§ãã
åé¿çãè¿œå ããã®ã¯æ¬åœã«ç°¡åã§ã
ç§ã¯ããããŸããããããããã¯ãã®ãããªäžè¬çã«äœ¿ãããã¿ã€ãã®ããã«å¿ èŠã§ã¯ãªãã¯ãã§ãã
ç§ã¯ä»æ¥ãã®åé¡ãçºèŠãïŒé¡§å®¢ããå ±åãããŸããïŒãStartup.csã®æ§æã䜿çšãã代ããã«Newtonsoft.Jsonã·ãªã¢ã©ã€ã¶ãŒã䜿çšããããã«ãã¹ãŠã®aspnetwebapiãšã¢ããªãå ã«æ»ãå¿ èŠããããŸãã
services.AddControllersïŒïŒ
.AddNewtonsoftJsonïŒoptions =>
{{
options.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
}ïŒ;
ç§ã®å Žåãããã€ãã®null蚱容TimeSpanïŒTimeSpanïŒïŒã䜿çšããSystem.Text.Jsonã¯ããã次ã®ããã«ã·ãªã¢ã«åããŸããã
{{
"hasValue"ïŒtrueã
"䟡å€"ïŒ {
ããããïŒ0ã
ãæ¥ãïŒ0ã
ãæéãïŒ0ã
ãããªç§ãïŒ0ã
ãåãïŒ0ã
ãç§ãïŒ0ã
"totalDays"ïŒ0ã
ãtotalHoursãïŒ0ã
"totalMilliseconds"ïŒ0ã
"totalMinutes"ïŒ0ã
"totalSeconds"ïŒ0
}
}
ããã«ãããWebãã©ãŠã¶ãŒã®javascriptãªããžã§ã¯ããããã³APIãæ¶è²»ããããŸããŸãªã¯ãã¹ãã©ãããã©ãŒã ïŒããŸããŸãªããã°ã©ãã³ã°èšèªãæå³ããïŒãã·ãªã¢ã©ã€ã¶ãŒã«å°ããªåé¡ãçºçããŸãã
Newtonsoft.Jsonã·ãªã¢ã©ã€ã¶ãŒãšåãã·ãªã¢ã«åã®çµæãæåŸ ããŸãã
{{
"timeSpan"ïŒ "00ïŒ00ïŒ00.0000000"ã
"nullTimeSpan"ïŒnull
}
ç§ã¯ä»æ¥ãã®åé¡ãèŠã€ããŸããïŒç§ã®é¡§å®¢ã«ãã£ãŠå ±åãããŸããïŒãããŠä»£ããã«Newtonsoft.Jsonã·ãªã¢ã©ã€ã¶ãŒã䜿çšããããã«ç§ã®aspnetwebapiãšã¢ããªã®ãã¹ãŠãå ã«æ»ãå¿ èŠããããŸã
@bashocz https://github.com/dotnet/corefx/issues/38641#issuecomment -540200476ã«èšèŒãããŠããåé¿çãæ©èœããªãã®ã¯ãªãã§ããïŒ
ïŒ38641ïŒã³ã¡ã³ãïŒã«èšèŒãããŠããåé¿çãããŸããããªãã®ã¯ãªãã§ããïŒ
@khellang TimeSpanã®ã·ãªã¢ã«åã¯å¥ã®éçºè ã«ãšã£ãŠã®åé¡ã§ããããšã匷調ãã泚æãåããããšæããŸãã System.Text.Jsonã«åãæ¿ãããã®ã§ãããããã€ãã®é害ããããŸãã
æ°é±éåã«æ°ããSystem.Text.Jsonã調ã¹ããšãããæ©èœãå®å šã§ã¯ãªãããšãããããŸããã dotnet / corefxïŒ41747ã®åé¡ãæèµ·ããä»ã®dotnet / corefxïŒ39031ãdotnet / corefxïŒ41325ãdotnet / corefxïŒ38650é¢é£ãææããŸããã ãã®ããããã¹ãŠã®å éšãã€ã¯ããµãŒãã¹ã¯åŒãç¶ãNewtonsoft.Jsonã䜿çšããŠããŸãã
çç±ã¯äžæã§ãããéçºè ã管çããŠãããªãã¯APIãWebã¢ããªã§ãä¿®æ£ããã®ãå¿ããŠããŸããã
ãšããã§ïŒç§ã¯æ¬çªã³ãŒãã§å¯èœãªéãåé¿çãé¿ããããã«ããŠããŸã..å°æ¥ãããç¶æããŠåé€ããã®ã¯é£ããã§ãã
@khellang ãåé¿çãæ©èœããªãããã§ã¯ãããŸããã ããã¯ãŸãã«ãã®ãããªåºæ¬çãªããšã§ãããéçºè ãåé¿çãè¿œå ããå¿ èŠã¯ãããŸããã .NET Core 3ã«å°å ¥ããã倧ããªæ©èœãšããŠããã®ãããªåºæ¬çãªå®è£ ãæ¬ ããŠããã¹ãã§ã¯ãããŸããã
@arisewanggithubã³ã³ãããŒã©ãŒã§äœ¿çšã§ããã°ããŒãã«èšå®ããããŸãã AddJsonOptions()
ãä»ããŠæ§æãããã JsonSerializerOptions
ã€ã³ã¹ã¿ã³ã¹ãJson()
ã³ã³ãããŒã©ãŒã¡ãœããã«æž¡ãããšãã§ããŸãã
ããã¯ãåé¿çãããããã«éããããåå ã§ããïŒïŒ
ããã¯ãåé¿çãããããã«éããããåå ã§ããïŒïŒ
API /åäœã®ææ¡ãã¬ãã¥ãŒãå®è£ ãè¡ããããŸã§ããã®åé¡ã¯æªè§£æ±ºã®ãŸãŸã§ãã ãããŸã§ã®éã httpsïŒ //github.com/dotnet/corefx/issues/38641#issuecomment -540200476ã«èšèŒãããŠããã³ã³ããŒã¿ãŒã䜿çšãããšãåé¿ããã®ã¯éåžžã«ç°¡åã§ãã
ããã«ãã£ãŠãããã¯ããã人ã®ããã«ã5.0ããããã®åã«äœ¿çšã§ããã³ã³ããŒã¿ãŒïŒJsonTimeSpanConverterïŒãå«ãNuGetããã±ãŒãžããããŸãïŒ Macross.Json.Extensions
TimeSpanããã³Nullable <TimeSpan>ã¿ã€ãããµããŒãããŸãã
ãããããããšãããã¯çãïŒ
ããã«ãã£ãŠãããã¯ããã人ã®ããã«ã5.0ããããã®åã«äœ¿çšã§ããã³ã³ããŒã¿ãŒïŒJsonTimeSpanConverterïŒãå«ãNuGetããã±ãŒãžããããŸãïŒ Macross.Json.Extensions
TimeSpanãšNullableããµããŒã
ã¿ã€ãã
ç§ã®ãã¹ãã«ãããšãnull蚱容å€åã¯ãã§ã«ãã¬ãŒã ã¯ãŒã¯ã«ãã£ãŠåŠçãããŠããŸãã 次ã®ãã®ä»¥äžã¯å¿ èŠãããŸããã
public class DelegatedStringJsonConverter<T> : JsonConverter<T>
where T : notnull
{
private static readonly bool s_typeAllowsNull = !typeof(T).IsValueType || Nullable.GetUnderlyingType(typeof(T)) != null;
private readonly Func<string, T> _parse;
private readonly Func<T, string> _toString;
public DelegatedStringJsonConverter(Func<string, T> parse, Func<T, string> toString)
{
_parse = parse;
_toString = toString;
}
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
// null tokens are handled by the framework except when the expected type is a non-nullable value type
// https://github.com/dotnet/corefx/blob/v3.1.4/src/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandleNull.cs#L58
if (!s_typeAllowsNull && reader.TokenType == JsonTokenType.Null)
throw new JsonException($"{typeof(T)} does not accept null values.");
return _parse(reader.GetString());
}
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
{
// value is presumably not null here as null values are handled by the framework
writer.WriteStringValue(_toString(value));
}
}
ïŒç·šéïŒãã¬ãŒã ã¯ãŒã¯ãœãŒã¹ã詳ãã調ã¹ãåŸãnullããŒã¯ã³/ nullå€ã®ãã§ãã¯ãåé·ã§ããããšãå€æããŸãããäžèšã®ã³ãŒãã¯ããã«å¿ããŠæŽæ°ãããŸãããïŒ
次ã«ã JsonSerializerOptions
ããã«æ§æããŸãã
options.Converters.Add(new DelegatedStringJsonConverter<TimeSpan>(
value => TimeSpan.Parse(value, CultureInfo.InvariantCulture),
value => value.ToString(null, CultureInfo.InvariantCulture)));
ãã®ãããªæ°è¡ã®äœåãªã³ãŒãã«å¯ŸåŠã§ããã®ã§ããã°ããµãŒãããŒãã£ã®äŸåé¢ä¿ãè¿œå ããã®ã¯è¯ãèãã§ã¯ãªããšæããŸãã çµå±ãç§ãã¡ã¯NPMã®åå°ã«ã¯ããŸããã ;ïŒ
ãã¡ããããã®ãããªåºæ¬çãªã¿ã€ãã®åé¿çããŸã£ããå¿ èŠãªãå Žåã¯ãæåã®æ¹æ³ã§ãã
@ adams85 FYI Nullableå€åã¯ãJsonConverterAttributeãšäžç·ã«äœ¿çšãããšããã°ãçºçããŸã<.NET5ã ïŒ32006ãåç §ããŠãã ããã ç§ã¯å人çã«ã°ããŒãã«æ§æãããå±æ§ã¹ã¿ã€ã«ã䜿çšããããšã奜ã¿ãŸãããããã£ãŠãæ¡åŒµæ©èœãšãã°ä¿®æ£ã§ãããã³ã³ããŒã¿ãŒã¯åªããŠããŸãã Macross.Json.Extensionsã«è¿œå ããŠãä»ã®äººã«ã圹ç«ã€å¯èœæ§ããããæã ãNPMã©ã³ããã«ç§»åããŠãããŸããªãããã«è¿œå ããŠãããããã§ããïŒ :)
@CodeBlanch JsonConverterAttribute
åºããŠãã®çãææããŠããã ãããããšãããããŸãã ããã¯ééããªãå®å
šãªç©èªã®äžéšã§ãã
ãããŠãã¡ãããããªããããã奜ããªããããªãã¯ç§ã®ã³ã³ããŒã¿ãŒãããªãã®libã«è¿œå ããããšãèš±å¯ãããŠããŸãã :)
.NET 5.0 Preview 5以éãSystem.Text.Jsonã䜿çšããŠãšã³ãã£ãã£ãJSONã«ã©ãŠã³ãããªãããããšCannot skip tokens on partial JSON
ãšã©ãŒãçºçããŸãã åé¡ã®ããè¡ãšæåã¯"Ticks":
ã³ãã³ã§ã
ãšã«ãããåé¿çã䜿çšãTimeSpan
ãé©åãªæ¹æ³ã§ã·ãªã¢ã«åãããš
.json
ãã¡ã€ã«ãéããŠããã®æ§é çãªæ å
ã®ãã¹ãŠã§ã·ãªã¢ã«åãããTimeSpan
ãèŠã€ããããã ãã«ãã¡ã€ã«ãéãããšãã®ç§ã®æåã®åå¿ã¯ãã確ãã«...ãã§ã¯ãªãã£ããããç§ãã+1ããŸããã
https://github.com/dotnet/runtime/issues/42356ã®@jsedlakããïŒ
çºè¡ã¿ã€ãã«
System.Text.Json.JsonSerializerã¯ã©ã¹ã¯ãTimeSpanããããã£ãã·ãªã¢ã«åã§ããŸãããéã·ãªã¢ã«åã§ããŸããã
å šè¬ç
ãã®åé¡ã瀺ããµã³ãã«ãããžã§ã¯ãã¯ã https ïŒ
WebApiã§TimeSpanããããã£ãè¿ããšãJSONã«æ£ããã·ãªã¢ã«åãããŸãã
[ { "forecastLength": { "ticks": 36000000000, "days": 0, "hours": 1, "milliseconds": 0, "minutes": 0, "seconds": 0, "totalDays": 0.041666666666666664, "totalHours": 1, "totalMilliseconds": 3600000, "totalMinutes": 60, "totalSeconds": 3600 } } ]
ãã ããããã©ã«ãã®ãã·ãªã¢ã©ã€ã¶æ¡åŒµæ©èœïŒ
HttpClient.GetFromJsonAsync
ïŒã¯ããããã£ãåŠçã§ããŸããã 空ã®TimeSpanãè¿ããŸãã ãªããžã§ã¯ããéã·ãªã¢ã«åããã«ã¯ãã«ã¹ã¿ã ã³ã³ããŒã¿ãŒã䜿çšããå¿ èŠããããŸããDotNetæ å ±
`.NET Core SDKïŒglobal.jsonãåæ ïŒïŒ
ããŒãžã§ã³ïŒ3.1.302
ã³ãããïŒ41faccf259å®è¡æç°å¢ïŒ
OSåïŒWindows
OSããŒãžã§ã³ïŒ10.0.20201
OSãã©ãããã©ãŒã ïŒWindows
RIDïŒwin10-x64
ããŒã¹ãã¹ïŒCïŒ\ Program Files \ dotnet \ sdk3.1.302 \ãã¹ãïŒãµããŒãã«åœ¹ç«ã¡ãŸãïŒïŒ
ããŒãžã§ã³ïŒ3.1.6
ã³ãããïŒ3acd9b0cd1ã€ã³ã¹ããŒã«ãããŠãã.NETCore SDKïŒ
3.1.302 [CïŒ\ Program Files \ dotnet \ sdk]ã€ã³ã¹ããŒã«ãããŠãã.NETCoreã©ã³ã¿ã€ã ïŒ
Microsoft.AspNetCore.All 2.1.20 [CïŒ\ Program Files \ dotnet \ shared \ Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.20 [CïŒ\ Program Files \ dotnet \ shared \ Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 3.1.6 [CïŒ\ Program Files \ dotnet \ shared \ Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.20 [CïŒ\ Program Files \ dotnet \ shared \ Microsoft.NETCore.App]
Microsoft.NETCore.App 3.1.6 [CïŒ\ Program Files \ dotnet \ shared \ Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 3.1.6 [CïŒ\ Program Files \ dotnet \ shared \ Microsoft.WindowsDesktop.App] `
.NET 6.0ã§ããã«å¯ŸåŠããããšæããŸããããã§ãã³ãã¥ããã£ã®è²¢ç®ãããã ããã°å¹žãã§ãã åœé¢ã®åé¿çã¯ã httpsïŒ //github.com/dotnet/runtime/issues/29932#issuecomment-540200476ãªã©ã®ã«ã¹ã¿ã ã³ã³ããŒã¿ãŒã䜿çšããããšã§ãã DateTime
ããã³DateTimeOffset
ã®
.NET6.0ã§ããã«å¯ŸåŠããããšæããŸã
.NET 5ã¯ãŸã ãªãªãŒã¹ãããŠããŸãããv6ãåŸ ã€ã®ã§ã¯ãªããv5ïŒsemverã§ã¯å€§ããªé倧ãªå€æŽv3 => v5ãèš±å¯ãããŠããŸãïŒã§åŒŸäžžãåãã ãããã®ã§ããã
ãã®æ©èœã5.0ã«é©åãããããšãã§ããŸããã§ããã 5.0ã®æ©èœã®æ®ãã®éšåãšäžç·ã«åªå é äœãä»ããå¿ èŠããããŸããããããã¯é©åããŸããã§ããã FWIWããã¯ã«ããã©ã€ã³ã«è¿ãã£ãã®ã§ãåããé ããªããŸããã
ã«ã¹ã¿ã ã³ã³ããŒã¿ãŒã䜿çšããç°¡åãªåé¿çãããäžåºŠåŒ·èª¿ããŸãã
public class TimeSpanConverter : JsonConverter<TimeSpan>
{
public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return TimeSpan.Parse(reader.GetString());
}
public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}
}
var options = new JsonSerializerOptions { Converters = { new TimeSpanConverter() };
JsonSerializer.Serialize(myObj, options);
...
@layomia ãç§ã¯ããã6.0ã§åãããšãã§ããŸãã
èªåã§jsonã³ã³ããŒã¿ãŒãæ§ç¯ããããšãéžæããå Žåã¯ãäžå€ã®ã«ã«ãã£ã䜿çšããããšããå§ãããŸãã
public class TimeSpanConverter : JsonConverter<TimeSpan>
{
public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return TimeSpan.Parse(reader.GetString(), CultureInfo.InvariantCulture);
}
public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString(format: null, CultureInfo.InvariantCulture));
}
}
ç§ã¯asp.netcore 3.1ã䜿çšããŠããŸãããä»æ¥ãã®åé¡ãçºçããŸããã null蚱容ã®ã¿ã€ã ã¹ãã³ãå«ãè¡ã§ã·ã°ãã«ãšã€ã³ã©ã€ã³ç·šéãåããteleriksã°ãªããã䜿çšããŠããããã€ããŒãã«ã¿ã€ã ã¹ãã³ããŒã¿ãå«ãŸããŠããããšãããããŸãããéã·ãªã¢ã«åã¯å€±æããŸãã ç§ã¯Macross.Json.Extensionsã©ã€ãã©ãªã䜿çšããjavascriptã®äžéšãäœãçŽããŠæ©èœãããããšã«ããŸããããçæ³çã§ã¯ãããŸãããããããé©åã«ä¿®æ£ãããããšãé¡ã£ãŠããŸãã
ãŸããISO8601圢åŒããæ¢ãã®å Žåã¯ã次ã䜿çšã§ããŸãã
`` `cïŒ
public class TimeSpanConverter : JsonConverter<TimeSpan>
{
public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var stringValue = reader.GetString();
return System.Xml.XmlConvert.ToTimeSpan(stringValue); //8601
}
public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options)
{
var stringValue = System.Xml.XmlConvert.ToString(value); //8601
writer.WriteStringValue(stringValue);
}
}
`` `
å°ãªããšã24æéã®TimeSpan
ãæ€èšããŠãã ãããããšãã°ã "24:00:00"
ã¯new TimeSpan(24, 0, 0)
ãšåçã§ããå¿
èŠããããŸãã
@gojanpaolo
å°ãªããšã24æéã®TimeSpanãæ€èšããŠãã ãããããšãã°ãã24:00:00ãã¯æ°ããTimeSpanïŒ24ã0ã0ïŒãšåçã§ããå¿ èŠããããŸãã
ããã¯å®éã«ã¯JSONã®ããšã§ã¯ãªããTimeSpan解æããžãã¯ã®äžéšã§ãã ç°¡åãªçãïŒã1.00ïŒ00ïŒ00ãã24æé䜿çšããŸãã é·ãçãïŒã24:00:00ããæåŸ ã©ããã«è§£æãããªãçç±ãç解ããããã«ããã°ããåã«ã©ã³ã¿ã€ã ã³ãŒãã調ã¹ãŠãããã°ã«æçš¿ããŸããã
æãåèã«ãªãã³ã¡ã³ã
æéã®æšæºãšã³ã³ãŒãã£ã³ã°ã¯ã XMLã
TimeSpan
ãè¡šãããã«äœ¿çšãããã®ã§ãããããã§ã«XmlConvert
ãšXsdDuration
å®è£ ãããŠããŸããhttps://github.com/dotnet/corefx/blob/6d723b8e5ae3129c0a94252292322fc19673478f/src/System.Private.Xml/src/System/Xml/XmlConvert.cs#L1128 -L1146
https://github.com/dotnet/corefx/blob/6d723b8e5ae3129c0a94252292322fc19673478f/src/System.Private.Xml/src/System/Xml/Schema/XsdDuration.cs#L229 -L236
ããŠãééããªãã
TimeSpan
èªäœãISO8601æéãã©ãŒãããã®è§£æãšãã©ãŒãããããµããŒãããã¯ãã§ãã ãã¶ããæåã®ã¹ããããšããŠãDateTime[Offset]
ã®ã©ãŠã³ãããªããïŒ "O"ã "o"ïŒåœ¢åŒæå®åã«äŒŒããæ°ããæšæºã®TimeSpan
圢åŒæååãè¿œå ããæ¹ãããã§ããããã ãã®åŸã«ã³ã³ããŒã¿ãŒãè¿œå ããã®ã¯æ¬åœã«ç°¡åã§ãã