JSON.NET 不会正确反序列化 class

JSON.NET won't deserialize class correctly

我正在尝试使 class(包含 NodaTimeZonedDateTime 属性)正确反序列化(使用 JSON.NET),但它没有似乎有效。

我也在引用和使用NodaTime.Serialization.JsonNet

序列化顺利,结果 JSON 正确,但反序列化生成错误的 ZonedDateTime 值。

在使用 NodaTime.Serialization.JsonNet 之前,我为 JSON.NET 编写了自己的自定义序列化程序,但我遇到了同样的问题。我注意到,我的自定义 JsonConverterReadJson() 方法正在生成正确的反序列化 ZonedDateTime 值,但是当 class 的构造函数托管 [=调用了 14=] 属性,ZonedDateTime 属性的输入值错误。

代码如下:

class Program
{
    static void Main(string[] args)
    {
        var obj = new ZonedTimeDetails(ZonedDateTime.FromDateTimeOffset(DateTime.Now), ZonedDateTime.FromDateTimeOffset(DateTime.Now.AddHours(1)), false);
        var json = JsonConvert.SerializeObject(obj, new FullJsonSerializerSettings());
        var obj2 = JsonConvert.DeserializeObject<ZonedTimeDetails>(json, new FullJsonSerializerSettings());
        return;
    }
}



public class FullJsonSerializerSettings : JsonSerializerSettings
{
    public FullJsonSerializerSettings()
    {
        ContractResolver = new AcTypeContractResolver((MemberInfo memberInfo) => {
            if (memberInfo is PropertyInfo pi)
            {
                var methodInfo = pi.GetSetMethod(true);
                if (methodInfo == null)
                {
                    return o => false;
                }
            }
            return o => true;
        });
        TypeNameHandling = TypeNameHandling.All;
        TypeNameAssemblyFormat = FormatterAssemblyStyle.Full;

        Converters.Add(NodaConverters.CreateZonedDateTimeConverter(DateTimeZoneProviders.Serialization));
    }
}



public class AcTypeContractResolver : DefaultContractResolver
{
    private readonly Predicate<object> _predicate;
    private readonly Func<MemberInfo, Predicate<object>> _predicateFactory;

    public AcTypeContractResolver(Predicate<object> predicate)
    {
        _predicate = predicate;
    }

    public AcTypeContractResolver(Func<MemberInfo, Predicate<object>> predicateFactory)
    {
        _predicateFactory = predicateFactory;
    }

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);

        property.Ignored = false;
        property.ShouldSerialize = _predicate ?? _predicateFactory?.Invoke(member);
        property.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
        return property;
    }
}



public class ZonedTimeDetails
{
    [JsonConstructor]
    public ZonedTimeDetails(ZonedDateTime zoneStart, ZonedDateTime zoneEnd, bool isOverflow = false)
    {
        ZonedStart = zoneStart;
        ZonedEnd = zoneEnd;
        IsOverflow = isOverflow;
    }

    public ZonedDateTime ZonedStart { get; private set; }
    public ZonedDateTime ZonedEnd { get; private set; }
    public bool IsOverflow { get; private set; }


    public DateTime Start => ZonedStart.ToDateTimeUnspecified();
    public DateTime End => ZonedEnd.ToDateTimeUnspecified();

    public double DurationMin => (ZonedEnd - ZonedStart).TotalMinutes;
}

这是整个项目,如果对您有帮助的话: https://mega.nz/#!hFc0RAbS!teJ3Y4JHqCx1aHxUVU4kUFs30xwTTyF6QTpRB0D1Fnw

如果有人知道出了什么问题,请告诉我。 据我所知,问题出在 ZonedTimeDetails class,但我相信这应该有效。 class 的 属性 名称与 ctor 参数名称相匹配,所以我不明白为什么我在反序列化过程中得到错误的值。

更新:

如果我为 ZonedDateTime 属性 public 创建设置器,它可以工作,但我需要 class 是不可变的。根据 SO (1, 2) 上的其他答案,此构造函数注入应该有效。

除此之外,在我使用 ZonedDateTime 之前,我在那个 class 中使用了 DateTime 属性。使用 setter private 一切正常。

问题是 ZonedTimeDetails 构造函数中的参数名称与 JSON 不匹配,后者是通过序列化同一个 class 创建的。 属性 名称有一个 d(例如 ZonedStart),而构造函数 属性 名称没有(zoneStart)。因此,当调用构造函数时,会将空结构传递给这些参数。

要修复,只需更改构造函数参数名称以匹配 属性 名称:

[JsonConstructor]
public ZonedTimeDetails(ZonedDateTime zonedStart, ZonedDateTime zonedEnd, bool isOverflow = false)
{
    ZonedStart = zonedStart;
    ZonedEnd = zonedEnd;
    IsOverflow = isOverflow;
}