我上了这个课:
public class Test
{
public Instant I { get; set;}
}
I
是Instant
,因为这在语义上是有意义的。
但是,我必须对此反序列化:
{
"i": "2018-10-25T18:34:11.911+00:00"
}
从这里:
{
"i": "2018-10-25T18:34:11.911+0000"
}
我该怎么做?
答案 0 :(得分:4)
使用CustomInstantPattern
的方法是一种很好的方法,但是我会避免使用任何.NET日期/时间类型。
相反,我将使用两个OffsetDateTimePattern
实例,一个实例带有冒号,一个实例不带有冒号,然后将它们与CompositePattern
组合在一起。然后,您可以仅委托给它,在需要时与Instant
进行相互转换。
这里是完整的示例代码:
using Newtonsoft.Json;
using NodaTime;
using NodaTime.Serialization.JsonNet;
using NodaTime.Text;
using System;
using System.Text;
class CustomInstantPattern : IPattern<Instant>
{
private readonly IPattern<OffsetDateTime> offsetDateTimePattern;
public CustomInstantPattern()
{
// Pattern explanation:
// - o<G> means "use the G Offset pattern" (to hour, minute or second, with colons, format +00 as Z)
// - o<I> means "use the I Offset pattern" (to hour, minute or second, without colons, format +00 as Z)
var patternWithColon = OffsetDateTimePattern.CreateWithInvariantCulture("uuuu'-'MM'-'dd'T'HH':'mm':'ss;FFFFFFFFFo<G>");
var patternWithoutColon = OffsetDateTimePattern.CreateWithInvariantCulture("uuuu'-'MM'-'dd'T'HH':'mm':'ss;FFFFFFFFFo<I>");
offsetDateTimePattern = new CompositePatternBuilder<OffsetDateTime>()
{
// The predicates here are for formatting. As the first always
// returns true, it doesn't really matter what the second does.
// The intention is that some values might not be formattable with
// all patterns, but that doesn't apply here.
{ patternWithColon, _ => true },
{ patternWithoutColon, _ => true }
}.Build();
}
public StringBuilder AppendFormat(Instant value, StringBuilder builder) =>
offsetDateTimePattern.AppendFormat(value.WithOffset(Offset.Zero), builder);
public string Format(Instant value) =>
offsetDateTimePattern.Format(value.WithOffset(Offset.Zero));
public ParseResult<Instant> Parse(string text) =>
offsetDateTimePattern.Parse(text).Convert(odt => odt.ToInstant());
}
class Entity
{
public Instant I { get; set; }
}
class Program
{
static void Main(string[] args)
{
var settings = new JsonSerializerSettings
{
DateParseHandling = DateParseHandling.None,
Converters = { new NodaPatternConverter<Instant>(new CustomInstantPattern()) }
};
string json = " { \"i\": \"2018-10-25T18:34:11.911+0000\" }";
Entity entity = JsonConvert.DeserializeObject<Entity>(json, settings);
Console.WriteLine(entity.I);
// Check it works with colons too
json = " { \"i\": \"2018-10-25T18:34:11.911+00:00\" }";
entity = JsonConvert.DeserializeObject<Entity>(json, settings);
Console.WriteLine(entity.I);
}
}
(这显示了Noda Time的两个问题-一个是嵌入式部分文档对于OffsetDateTime
模式是不正确的,另一个是我们没有用于“扩展ISO”的标准模式,非常烦人。我会尽力解决这两个问题。
答案 1 :(得分:0)
我已经能够使用一种特殊的模式来解决它:
public class CustomInstantPattern : IPattern<Instant>
{
public StringBuilder AppendFormat(Instant value, StringBuilder builder)
{
return builder.AppendFormat("s", value.ToDateTimeOffset());
}
public string Format(Instant value)
{
return value.ToDateTimeOffset().ToString("s");
}
public ParseResult<Instant> Parse(string text)
{
try
{
return ParseResult<Instant>.ForValue(DateTimeOffset.Parse(text, CultureInfo.InvariantCulture).ToInstant());
}
catch (Exception ex)
{
return ParseResult<Instant>.ForException(() => throw ex);
}
}
}
var settings = new JsonSerializerSettings
{
DateParseHandling = DateParseHandling.None,
Converters =
{
new NodaPatternConverter<Instant>(new CustomInstantPattern()),
}
};
var converted = JsonConvert.DeserializeObject<Test>("{ 'I': '2018-10-25T18:34:11.911+0000'}", settings);
这是正确的方法吗?