"从'日期时间'到'Int64'的强制转换无效。反序列化 JSON 字符串时



我正在解析一个带有json元素的大数据文件。对于某些字符串而言,次要化失败。

 Exception  = Invalid cast from 'DateTime' to 'Int64'.
 Message    = Error converting value 3/28/2172 12:00:00 AM to type 'System.Int64'.  Path 'ProductDetail.productId', line 1, position 4003."

并非所有字符串发生错误,但似乎表明该值被解释为DateTime值。虽然,它在关联类中定义为

我可以强迫要解释为的值?

productDetail.productid定义为以下类型的成员:

   public class ProductDetail
    {
        public string accreditedInvestorInd { get; set; }
        public string accrueAcreteInd { get; set; }
        public DateTime issueDate { get; set; }
        // ... truncated for simplicity
        public long productId { get; set; }
       // ... truncated for simplicity
        public string wkndHolPayInd { get; set; }
        public string zeroCouponInd { get; set; }
    }

我尝试使用转换器属性未能成功,以期强制使用不同的解释。(不确定我是否正确使用)...

    [JsonConverter(typeof(string))]
    public long productId { get; set; }

另外,我正在使用自定义DateTime格式。

这是我试图进行的大型数据文件的子集,该文件与ProductDetail相对应:

{"accrueAcreteInd":"Y","callableInd":"Y","calledInd":"N","cpnCurrency":"USD","cpnPmtFreqCode":"S","cpnRate":"2.8","curAmtOutstanding":"7825000.0","currencyCode":"USD","cusip":"3130H0AX1","datedDate":"20160303","dayCountMonthCode":"30","dayCountYearCode":"360","daysToSettle":"1","dtcEligibleInd":"Y","eomPmtInd":"N","exchange":"TRACE","fatcaCode":"1","firstCpnPmtDate":"20160901","hqlaCode":"2A","identifier":"3130H0AX1","identifierType":"cusip","inDefaultInd":"N","infoSourceCode":"R21RB","intAccrued":".91777778","intTypeCode":"FIX","is144aInd":"N","issueCountry":"US","issueDate":"20160303","issuePrice":"100.0","issuerIndustryCode":"11","issuerName":"FARMER MAC","issuerTicker":"FAMCA","lastCpnPmtDate":"20250901","lastUpdateTime":"20160830","lastUpdateTimeExt":"00:06:58","longDesc":"FAMCA 2.8 03/01/2026","maturityDate":"20260301","minDenom":"1000.0","minParAmount":"1000.0","mktSectorDes":"Govt","mtnInd":"Y","nextCallDate":"20170301","nextCallPrice":"100.0","nextCpnPmtDate":"20170301","origIssueAmt":"7825000.0","prevCpnPmtDate":"20160901","primaryIssInd":"Y","privatePlacementInd":"N","productId":"21720328","productTypeCode":"FRMNT","putableInd":"N","pxCleanInd":"Y","redempVal":"100.0","regSInd":"N","restrictedInd":"N","secHoldInd":"N","securityType":"FAMCCL","series":"NOTZ","shortDesc":"FAMCA 2.8 03/26","sinkableInd":"N","traceEligibleInd":"N","truePutInd":"N","wkndHolPayInd":"N","zeroCouponInd":"N"}

这是我试图对子集进行估算的方式,其中Line是上面的JSON字符串:

var dateFormatSettings = new JsonSerializerSettings { DateFormatString = "yyyyMMdd" };
var detail = JsonConvert.DeserializeObject<ProductDetail>(Line, dateFormatSettings);

这是简化的JSON的完整例外:

Newtonsoft.Json.JsonSerializationException: Error converting value 3/28/2172 12:00:00 AM to type 'System.Int64'. Path 'productId', line 1, position 1117. ---> System.InvalidCastException: Invalid cast from 'DateTime' to 'Int64'.
   at System.DateTime.System.IConvertible.ToInt64(IFormatProvider provider)
   at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType)
   --- End of inner exception stack trace ---
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.EnsureType(JsonReader reader, Object value, CultureInfo culture, JsonContract contract, Type targetType)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
   at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)

问题与您使用的特定DateFormatString有关:

var dateFormatSettings = new JsonSerializerSettings { DateFormatString = "yyyyMMdd" };

JSON没有关于日期的字面语法,因此,在低级别,JSON.NET进行一些模式匹配以识别使用DateFormatString设置的字符串。不幸的是,您的DateFormatString设置yyyyMMdd匹配以下JSON属性:

   "issueDate":"20160303", // Should deserialize to a DateTime
   "productId":"21720328", // Should deserialize to a long

等等,虽然第一个被正确识别为日期,但第二个也是,最终在较高的代码级别引起"Invalid cast from 'DateTime' to 'Int64'."异常。这是一个边缘情况,因为与long成员相对应的JSON字符串值是longDateTime,这是出乎意料的,但这可以说是JSON.NET中的错误。

您有几个解决方法:

  1. 通过设置JsonSerializerSettings.DateParseHandling = DateParseHandling.None禁用自动日期识别:

    var dateFormatSettings = new JsonSerializerSettings
    {
        DateParseHandling = DateParseHandling.None,
        DateFormatString = "yyyyMMdd"
    };
    

    ,尽管有降低自动识别,但仍将明确键入为DateTime的成员仍将正确化。

  2. 使用IsoDateTimeConverter { DateTimeFormat = "yyyyMMdd" }而不是设置JsonSerializerSettings.DateFormatString

    var dateFormatSettings = new JsonSerializerSettings
    {
        Converters = { new IsoDateTimeConverter { DateTimeFormat = "yyyyMMdd" } }
    };
    

    成员明确键入为DateTime,将使用您所需的格式字符串进行审理,而将用于低级自动识别的模式不变。

样本小提琴再现问题并证明了两个解决方法。

相关内容

  • 没有找到相关文章

最新更新