gpt4 book ai didi

c# - json.net IValueProvider SetValue抛出异常丢失

转载 作者:行者123 更新时间:2023-11-30 21:43:31 27 4
gpt4 key购买 nike

我有一个 CotractResolver 返回每个 DateTime 属性的时间部分的属性(以便用户可以单独设置时间)。我有一个 TimeValueProvider,它有一个 SetValue 方法,如下所示:

public void SetValue(object target, object value)
{
try
{
var time = value as string;
var originalValue = _propertyInfo.GetValue(target);
if (value == null)
{
_propertyInfo.SetValue(target, originalValue);
}

else if (string.IsNullOrWhiteSpace(time))
{
var originalDateTime = (DateTime?) originalValue ?? SqlDateTime.MinValue.Value;
_propertyInfo.SetValue(target,
new DateTime(originalDateTime.Year, originalDateTime.Month, originalDateTime.Day, 0, 0, 0));
}
else
{
var currentValue = GetCurrentValue(_propertyInfo.GetValue(target));
var convertedDate = TimeSpan.Parse(time, new DateTimeFormatInfo {LongTimePattern = "HH:mm:ss"});
var finalValue = new DateTime(currentValue.Year, currentValue.Month, currentValue.Day,
convertedDate.Hours, convertedDate.Days, convertedDate.Seconds);
_propertyInfo.SetValue(target, finalValue);
}
}
catch (InvalidDataException)
{
throw new ValidationException(new[]
{
new ValidationError
{
ErrorMessage = "Time is not correct",
FieldName = _propertyInfo.Name,
TypeName = _propertyInfo.DeclaringType.FullName
}
});
}
}

问题是每当我传递一个无效的数字时,例如 99:99,TimeSpan.Parse 就会抛出异常,但我没有在这个方法之外得到它,因此 Json。 Net 反序列化对象。我检查了我的代码,但找不到导致此类行为的任何一般异常处理。我在这里是否遗漏了有关契约(Contract)解析器和值(value)提供者的信息?

更新:这是我配置 Json.net 的方式:

config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new EntityContractResolver();
config.Formatters.JsonFormatter.SerializerSettings.ObjectCreationHandling = ObjectCreationHandling.Replace;

config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;

最佳答案

您的问题是您正在尝试解析 IValueProvider.SetValue() 中的 JSON 字符串.但是,值提供程序仅在 JSON 被反序列化后才被调用。。其目的是在容器对象内部设置反序列化值。因此,您当前的 SetValue() 方法实际上从未执行任何操作,因为:

  • 如果反序列化成功,传入的对象值将是一个DateTime,而不是一个字符串。
  • 如果日期字符串无效,则根本不会调用该方法,因为已经抛出异常。

您需要做的是使用 custom JsonConverter解析 JSON 日期字符串并将其与现有值组合。 JsonConverter.ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)有一个包含属性当前值的参数 existingValue,所以这很简单:

public class DateTimeConverter : JsonConverter
{
public override bool CanWrite { get { return false; } }

public override bool CanConvert(Type objectType)
{
return objectType == typeof(DateTime) || objectType == typeof(DateTime?);
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var token = JToken.Load(reader);
if (token.Type == JTokenType.Date)
{
// Json.NET already parsed the date successfully. Return it.
return (DateTime)token;
}
else
{
TimeSpan span;
if (token.Type == JTokenType.TimeSpan)
{
// Not sure this is actually implemented, see
// http://stackoverflow.com/questions/13484540/how-to-parse-a-timespan-value-in-newtonsoft-json/13505910#13505910
span = (TimeSpan)token;
}
else
{
var timeString = (string)token;
if (String.IsNullOrWhiteSpace(timeString))
span = new TimeSpan();
else
{
try
{
span = TimeSpan.Parse(timeString, new DateTimeFormatInfo { LongTimePattern = "HH:mm:ss" });
}
catch (Exception ex)
{
throw new ValidationException(ex.Message);
}
}
}
var currentValue = (DateTime?)existingValue ?? SqlDateTime.MinValue.Value;

// Combine currentValue & TimeSpan and return. REPLACE THIS WITH YOUR OWN LOGIC.
// I don't really know how you want to do this.
return new DateTime(currentValue.Year, currentValue.Month, currentValue.Day) + span;
}
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}

然后将其应用到您的 EntityContractResolver 中,如下所示:

public class EntityContractResolver : DefaultContractResolver
{
DateTimeConverter converter = null;

DateTimeConverter Converter
{
get
{
if (converter == null)
converter = Interlocked.CompareExchange(ref converter, new DateTimeConverter(), null);
return converter;
}
}

protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var jProperty = base.CreateProperty(member, memberSerialization);
if (jProperty.PropertyType == typeof(DateTime) || jProperty.PropertyType == typeof(DateTime?))
{
jProperty.Converter = jProperty.MemberConverter = Converter;
}
return jProperty;
}
}

样本 fiddle .

关于c# - json.net IValueProvider SetValue抛出异常丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41671045/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com