我正在解析一个带有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字符串值是long
和DateTime
,这是出乎意料的,但这可以说是JSON.NET中的错误。
您有几个解决方法:
通过设置
JsonSerializerSettings.DateParseHandling = DateParseHandling.None
禁用自动日期识别:var dateFormatSettings = new JsonSerializerSettings { DateParseHandling = DateParseHandling.None, DateFormatString = "yyyyMMdd" };
,尽管有降低自动识别,但仍将明确键入为
DateTime
的成员仍将正确化。使用
IsoDateTimeConverter { DateTimeFormat = "yyyyMMdd" }
而不是设置JsonSerializerSettings.DateFormatString
。var dateFormatSettings = new JsonSerializerSettings { Converters = { new IsoDateTimeConverter { DateTimeFormat = "yyyyMMdd" } } };
成员明确键入为
DateTime
,将使用您所需的格式字符串进行审理,而将用于低级自动识别的模式不变。
样本小提琴再现问题并证明了两个解决方法。