我正在尝试使一个类(包含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的其他答案(1,2),此构造函数注入应该有效。
除此之外,在使用ZonedTimeDetails
之前,我在该类中使用了ZonedDateTime
属性。私密的二传手也没问题。
答案 0 :(得分:3)
问题是ZonedTimeDetails
构造函数中的参数名称与JSON匹配,而JSON是通过序列化同一类而创建的。属性名称具有d
(例如ZonedStart
),而构造函数属性名称没有(zoneStart
)。因此,在调用构造函数时,会将空结构传递给这些参数。
要解决此问题,只需更改构造函数参数名称以使其与属性名称匹配:
[JsonConstructor]
public ZonedTimeDetails(ZonedDateTime zonedStart, ZonedDateTime zonedEnd, bool isOverflow = false)
{
ZonedStart = zonedStart;
ZonedEnd = zonedEnd;
IsOverflow = isOverflow;
}