我尝试使用NodaTime来解释从第三方API检索的日期。日期在同一个响应中出现了一系列令人讨厌的格式,我特别遇到的问题类似于:
{
"ShortDate": "2017-01-01",
"LongDate": "01 January 2017"
}
我可以使用NodaPatternConverter正确地反序列化一种格式,但不能同时使用两种格式。
显示问题的一个简单示例如下:
using Newtonsoft.Json;
using NodaTime;
using NodaTime.Serialization.JsonNet;
using NodaTime.Text;
namespace NodaLocalDateConverterTest
{
class ExampleDatedModel
{
public LocalDate ShortDate { get; set; }
public LocalDate LongDate { get; set; }
}
class Program
{
static void Main(string[] args)
{
var exampleJsonString =
@"{
""ShortDate"": ""2017-01-01"",
""LongDate"": ""01 January 2017""
}";
var serialisationSettings = new JsonSerializerSettings();
//NodaTime default converter supports ShortDate format
serialisationSettings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
//Exception on LongDate property
var deserialisedExample1 = JsonConvert.DeserializeObject<ExampleDatedModel>(exampleJsonString, serialisationSettings);
serialisationSettings.Converters.Remove(NodaConverters.LocalDateConverter);
serialisationSettings.Converters.Add(new NodaPatternConverter<LocalDate>(LocalDatePattern.CreateWithInvariantCulture("dd MMMM yyyy")));
//Exception on ShortDate property
var deserialisedExample2 = JsonConvert.DeserializeObject<ExampleDatedModel>(exampleJsonString, serialisationSettings);
}
}
}
使用默认序列化器会在LongDate属性上抛出异常:
未处理的类型异常 &#39; NodaTime.Text.UnparsableValueException&#39;发生在 Newtonsoft.Json.dll
其他信息:值字符串与所需值不匹配 来自格式字符串&#34; yyyy&#34;的数字。正在解析的价值:&#39; ^ 01月1日 2017&#39 ;. (^表示错误位置。)
替换自定义模式转换器会在ShortDate属性上引发异常:
未处理的类型异常 &#39; NodaTime.Text.UnparsableValueException&#39;发生在 Newtonsoft.Json.dll
附加信息:值字符串与简单字符串不匹配 格式字符串中的字符&#34; &#34 ;.正在解析的价值:&#39; 20 ^ 17-01-01&#39;。 (^表示错误位置。)
原则上我认为我可以为这两个属性使用两个不同的转换器,例如
class ExampleDatedModel
{
[JsonConverter(typeof(ShortDateConverter)]
public LocalDate ShortDate { get; set; }
[JsonConverter(typeof(LongDateConverter)]
public LocalDate LongDate { get; set; }
}
但是我不知道如何使用NodaTime的NodaPatternConverter和属性,因为你可以用模式实例化转换器。
documentation有用地说&#34;可以使用NodaPatternConverter轻松地从模式创建自定义转换器。&#34;但是没有给出任何例子!
我可能的解决方案
但我希望我只是错过了一种标记资源类以使用现有转换器的方法。
答案 0 :(得分:3)
这确实似乎是我们没有考虑过的用例。对于“正常”使用,密封NodaPatternConverter
感觉就像是正确的方法 - 但是当类型必须指定JsonConverter
而不是实例化时,密封是令人沮丧的。我filed an issue要在2.0中解决这个问题,我希望在下个月左右发布。 (它是now implemented - 拉取请求也显示了样本用法。)
然而,与此同时,我可能将只是分叉NodaPatternConverter
- 并添加一条评论,说明只有在你可以使用2.0之前。
你可能想稍微调整一下,因为你可能不需要额外的验证,假设你控制了所有要序列化数据的代码 - 如果你不需要担心非ISO {{ 1}}值,您可能不需要验证。
另一个方面是,如果你只是使用转换器解析,你根本不需要写作方 - 你可能只是为此抛出异常,可能
开封LocalDate
的替代方法是使用简单的(抽象)NodaPatternConverter
类型,该类型委托给另一个DelegatingConverterBase
。典型用法如下:
JsonConverter
这可能是一个更优雅的问题分离 - 并且可以用更少的代码实现,直到它也是Noda Time的一部分:
public sealed class ShortDateConverter : DelegatingConverterBase
{
public ShortDateConverter() : base(NodaConverters.LocalDate) {}
}