JSON.NET无法正确反序列化类

时间:2019-08-23 11:12:53

标签: json.net deserialization nodatime

我正在尝试使一个类(包含NodaTime的{​​{1}}属性)正确地反序列化(使用JSON.NET),但似乎不起作用。

我正在引用并且也使用ZonedDateTime

序列化进行得很好,并且生成的JSON是正确的,但是反序列化会生成错误的NodaTime.Serialization.JsonNet值。

在使用ZonedDateTime之前,我已经为JSON.NET编写了自己的自定义序列化程序,并且遇到了同样的问题。我注意到的是,自定义NodaTime.Serialization.JsonNet的{​​{1}}方法正在生成正确的反序列化ReadJson()值,但是当托管JsonConverter属性的类的构造函数出现时被调用时,ZonedDateTime属性的输入值是错误的。

代码如下:

ZonedDateTime

这是整个项目,如果可以帮助您: https://mega.nz/#!hFc0RAbS!teJ3Y4JHqCx1aHxUVU4kUFs30xwTTyF6QTpRB0D1Fnw

如果有人知道出了什么问题,请告诉我。 据我所知,问题出在ZonedDateTime类中,但是我认为这应该可以解决。该类的属性名称与ctor参数名称匹配,因此我无法理解为什么在反序列化期间在那里得到错误的值。

更新:

如果我公开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; } 属性的设置器,它可以工作,但是我需要该类是不可变的。根据SO的其他答案(12),此构造函数注入应该有效。

除此之外,在使用ZonedTimeDetails之前,我在该类中使用了ZonedDateTime属性。私密的二传手也没问题。

1 个答案:

答案 0 :(得分:3)

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

要解决此问题,只需更改构造函数参数名称以使其与属性名称匹配:

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