gpt4 book ai didi

c# - 如何在同一个 JSON 对象中反序列化不同的 NodaTime LocalDate 模式

转载 作者:行者123 更新时间:2023-11-30 21:42:42 25 4
gpt4 key购买 nike

我正在尝试使用 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 属性上抛出异常:

An unhandled exception of type 'NodaTime.Text.UnparsableValueException' occurred in Newtonsoft.Json.dll

Additional information: The value string does not match the required number from the format string "yyyy". Value being parsed: '^01 January 2017'. (^ indicates error position.)

替换为自定义模式转换器会在 ShortDate 属性上引发异常:

An unhandled exception of type 'NodaTime.Text.UnparsableValueException' occurred in Newtonsoft.Json.dll

Additional information: The value string does not match a simple character in the format string " ". Value being parsed: '20^17-01-01'. (^ indicates error position.)

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

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

[JsonConverter(typeof(LongDateConverter)]
public LocalDate LongDate { get; set; }
}

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

documentation有用地说“可以使用 NodaPatternConverter 从模式轻松创建自定义转换器。”但没有给出任何例子!

我考虑过的可能的解决方案是

  • 创建一对从 NodaPatternConverter 派生的转换器,它们是为两种模式配置的。
    • NodaPatternConverter 是密封的,因此不能继承。
  • 创建一对从 JsonConverter 派生的转换器来处理这两种模式
    • 我猜这些会在内部调用两个版本的 LocalDatePattern.Parse 和不同的模式。
    • 重新实现整个 JsonConverter 似乎有些矫枉过正。
  • 将日期反序列化为字符串,然后再转换日期。
    • 需要为具有混合类型的每个类实现。
    • 使从 API 获取资源的通用方法更加复杂。

但我希望我只是缺少一种标记资源类以使用现有转换器的方法。

最佳答案

这似乎确实是我们没有考虑过的用例。对于“正常”使用,密封 NodaPatternConverter 感觉是正确的方法 - 但是当 JsonConverter 必须由 type 指定而不是实例化时,密封令人沮丧。我有 filed an issue在 2.0 中解决这个问题,我希望在下个月左右发布。 (它是 now implemented - 拉取请求也显示示例用法。)

然而,与此同时,我可能只是 fork NodaPatternConverter - 并添加一条评论说它只有在您可以使用 2.0 之前才存在。

您可能需要稍微削减它,因为您可能不需要额外的验证,假设您控制所有将序列化数据的代码 - 如果您不需要担心非 ISO LocalDate 值,您可能不需要验证。

另一方面是,如果您只是使用转换器解析,那么您根本不需要编写端 - 您现在可以为此抛出一个异常,可能.

解封 NodaPatternConverter 的替代方法是使用一个简单的(抽象的)DelegatingConverterBase 类型,它委托(delegate)给另一个 JsonConverter。典型用法类似于:

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

这可能是一种更优雅的关注点分离 - 并且在成为 Noda Time 的一部分之前可以用更少的代码实现:

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);
}

关于c# - 如何在同一个 JSON 对象中反序列化不同的 NodaTime LocalDate 模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42351272/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com