【发布时间】:2019-08-23 11:12:53
【问题描述】:
我正在尝试正确反序列化一个类(包含 NodaTime 的 ZonedDateTime 属性)(使用 JSON.NET),但它似乎不起作用。
我也在引用和使用NodaTime.Serialization.JsonNet。
序列化顺利,生成的 JSON 正确,但反序列化生成错误的ZonedDateTime 值。
在使用NodaTime.Serialization.JsonNet 之前,我为 JSON.NET 编写了自己的自定义序列化程序,但遇到了同样的问题。我注意到的是,我的自定义 JsonConverter 的 ReadJson() 方法正在生成正确的反序列化 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 上的其他答案(1,2),这个构造函数注入应该可以工作。
除此之外,在我使用ZonedDateTime 之前,我在该类中使用了DateTime 属性。并且设置器私有的一切正常。
【问题讨论】:
-
“除此之外,在我使用 ZonedDateTime 之前,我在该类中使用了 DateTime 属性” - 我怀疑在这种情况下您有不同的构造函数参数名称;与属性名称匹配的。
标签: json.net deserialization nodatime