我如何在同一JSON对象内进行不同的nodatime locatime locate模式



我正在尝试使用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);
        }
    }
}

使用默认串行器给出了长期属性的异常:

类型的未经手的例外 'Nodatime.text.unparsableValueException'发生在 newtonsoft.json.dll

附加信息:值字符串与所需的不匹配 格式字符串" yyyy"的编号。分析价值:'^1月1日 2017'。(^表示错误位置。)

用自定义模式转换器替换在Shortdate属性上抛出异常:

类型的未经手的例外 'Nodatime.text.unparsableValueException'发生在 newtonsoft.json.dll

附加信息:值字符串与简单的 格式字符串的字符"。解析值:'20^17-01-01'。 (^表示错误位置。)

原则上,我认为我可以使用两个不同的转换器作为两个属性,例如

class ExampleDatedModel
{
    [JsonConverter(typeof(ShortDateConverter)]
    public LocalDate ShortDate { get; set; }
    [JsonConverter(typeof(LongDateConverter)]
    public LocalDate LongDate { get; set; }
}

但是,我看不到如何将Nodatime的NodaPatternConverter与属性一起使用,因为您无法使用模式实例化转换器。

该文档对"可以使用NodaPatternConverter轻松创建自定义转换器"。但没有任何例子!

我可能的解决方案是

  • 创建一对源自NodapatternConverter的转换器,该转换器是为两个模式配置的。
    • nodapatternconverter已密封,因此不能继承。
  • 创建一对源自jsonconverter的转换器来处理这两种模式
    • 我想这些会在内部使用不同模式的两个版本。
    • 整个JSONCONVERTER的重新实现似乎过高。
  • 当字符串随后转换日期时,
  • 可以将日期审理。
    • 需要为具有多种类型的每个类实施。
    • 使通用方法从API获取资源更复杂。

,但我希望我只是错过了一种标记使用现有转换器的资源类别的方法。

这确实是我们未考虑的用例。对于"正常"使用情况,密封NodaPatternConverter感觉就像是正确的方法 - 但是,当必须通过 type 而不是实例化指定JsonConverter时,密封件令人沮丧。我已经提出了一个问题,以在2.0中解决此问题,希望下个月左右发布。(现在已实施 - 拉请请求也显示了示例使用量。)

但是,与此同时,我可能 fork NodaPatternConverter-添加评论说它只有在那里,直到您可以使用2.0。

您可能需要对其进行修剪一下,因为您可能不需要额外的验证,假设您控制所有将要序列化数据的代码 - 如果您不必担心非ISO LocalDate值,您可能不需要验证。

另一个方面是,如果您只使用转换器来解析,您根本就不需要写作方面 - 目前您可能会派出一个例外。

启用NodaPatternConverter的替代方法是具有简单的(抽象)DelegatingConverterBase类型,该类型将其委派给另一个JsonConverter。典型的用法将是:

public sealed class ShortDateConverter : DelegatingConverterBase
{
    public ShortDateConverter() : base(NodaConverters.LocalDate) {}
}

这可能是更优雅的关注点 - 并且可以用更少的代码来实现,直到它也是NODA时间的一部分:

public abstract class DelegatingConverterBase : JsonConverter
{
    private readonly JsonConverter original;
    protected DelegatingConverterBase(JsonConverter original)
    {
        this.original = original;
    }
    public override void WriteJson(
        JsonWriter writer, object value, JsonSerializer serializer) =>
        original.WriteJson(writer, value, serializer);
    public override object ReadJson(
        JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) =>
        original.ReadJson(reader, objectType, existingValue, serializer);
    public override bool CanRead => original.CanRead;
    public override bool CanWrite => original.CanWrite;
    public override bool CanConvert(Type objectType) => original.CanConvert(objectType);
}

相关内容

  • 没有找到相关文章

最新更新