【问题标题】:JSON.NET won't deserialize class correctlyJSON.NET 不会正确反序列化类
【发布时间】:2019-08-23 11:12:53
【问题描述】:

我正在尝试正确反序列化一个类(包含 NodaTimeZonedDateTime 属性)(使用 JSON.NET),但它似乎不起作用。

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

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

在使用NodaTime.Serialization.JsonNet 之前,我为 JSON.NET 编写了自己的自定义序列化程序,但遇到了同样的问题。我注意到的是,我的自定义 JsonConverterReadJson() 方法正在生成正确的反序列化 ZonedDateTime 值,但是当调用托管 ZonedDateTime 属性的类的构造函数时, 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 类中,但我相信这应该可行。该类的属性名称与 ctor 参数名称匹配,因此我无法理解为什么在反序列化期间我会在其中得到错误的值。

更新:

如果我将 ZonedDateTime 属性的设置器公开,它可以工作,但我需要该类是不可变的。根据 SO 上的其他答案(12),这个构造函数注入应该可以工作。

除此之外,在我使用ZonedDateTime 之前,我在该类中使用了DateTime 属性。并且设置器私有的一切正常。

【问题讨论】:

  • “除此之外,在我使用 ZonedDateTime 之前,我在该类中使用了 DateTime 属性” - 我怀疑在这种情况下您有不同的构造函数参数名称;与属性名称匹配的。

标签: json.net deserialization nodatime


【解决方案1】:

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

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

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

【讨论】:

  • 天啊!现在我注意到我在名称中缺少d! :( 废话。我太傻了。
猜你喜欢
  • 2012-06-15
  • 2023-03-14
  • 1970-01-01
  • 2012-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多