C# Json—从Json获取反序列化对象的对应行号,以便更好地处理错误
我的应用程序接受来自我反序列化和处理的客户端的长JSON模板。我希望向客户提供更好的错误处理信息,这些信息包含JSON文本中无效对象的行号。请注意,这是针对后处理过程中发生的错误,而不是针对反序列化过程中发生的错误,因为这已经由Newtonsoft处理 例如,我有下面的JSON及其对应的.Net类型C# Json—从Json获取反序列化对象的对应行号,以便更好地处理错误,c#,json.net,C#,Json.net,我的应用程序接受来自我反序列化和处理的客户端的长JSON模板。我希望向客户提供更好的错误处理信息,这些信息包含JSON文本中无效对象的行号。请注意,这是针对后处理过程中发生的错误,而不是针对反序列化过程中发生的错误,因为这已经由Newtonsoft处理 例如,我有下面的JSON及其对应的.Net类型 { "Version": "1.0.0.0", "MyComplexObject": [ { "Prop1":
{
"Version": "1.0.0.0",
"MyComplexObject": [
{
"Prop1": "Val1",
"Prop2": "Val2",
"Prop3": 1
}
]
}
public class MyComplexObject
{
[JsonProperty]
public string Prop1 { get; set; }
[JsonProperty]
public string Prop2 { get; set; }
[JsonProperty]
public int Prop3 { get; set; }
**public int LineNumber;
public int LinePosition;**
}
public class RootObject
{
[JsonProperty]
public string Version { get; set; }
[JsonProperty]
public List<MyComplexObject> MyComplexObject { get; set; }
}
{
“版本”:“1.0.0.0”,
“MyComplexObject”:[
{
“Prop1”:“Val1”,
“Prop2”:“Val2”,
“建议3”:1
}
]
}
公共类MyComplexObject
{
[JsonProperty]
公共字符串Prop1{get;set;}
[JsonProperty]
公共字符串Prop2{get;set;}
[JsonProperty]
公共int Prop3{get;set;}
**公共整数行号;
公共位置**
}
公共类根对象
{
[JsonProperty]
公共字符串版本{get;set;}
[JsonProperty]
公共列表MyComplexObject{get;set;}
}
我希望在反序列化时填充LineNumber和LinePosition属性,以便以后使用。我目前正在使用下面的代码反序列化JSON
JsonConvert.DeserializeObject<RootObject>(value: rawJson,settings: mysettings);
JsonConvert.DeserializeObject(值:rawJson,设置:mysettings);
感谢您的回复我通过实现如下自定义转换器,解决了这个问题。任何实现JsonLineInfo的类在反序列化时都会自动获取自身的行号信息及其属性
public class LineInfo
{
[JsonIgnore]
public int LineNumber { get; set;}
[JsonIgnore]
public int LinePosition { get; set;}
}
public abstract class JsonLineInfo : LineInfo
{
[JsonIgnore]
public Dictionary<string, LineInfo> PropertyLineInfos { get; set; }
}
class LineNumberConverter : JsonConverter
{
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException("Converter is not writable. Method should not be invoked");
}
public override bool CanConvert(Type objectType)
{
return typeof(JsonLineInfo).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType != JsonToken.Null)
{
int lineNumber = 0;
int linePosition = 0;
var jsonLineInfo = reader as IJsonLineInfo;
if (jsonLineInfo != null && jsonLineInfo.HasLineInfo())
{
lineNumber = jsonLineInfo.LineNumber;
linePosition = jsonLineInfo.LinePosition;
}
var rawJObject = JObject.Load(reader);
var lineInfoObject = Activator.CreateInstance(objectType) as JsonLineInfo;
serializer.Populate(this.CloneReader(reader, rawJObject), lineInfoObject);
return this.PopulateLineInfo(
lineInfoObject: lineInfoObject,
lineNumber: lineNumber,
linePosition: linePosition,
rawJObject: rawJObject);
}
return null;
}
private JsonReader CloneReader(JsonReader reader, JObject jobject)
{
var clonedReader = jobject.CreateReader();
clonedReader.Culture = reader.Culture;
clonedReader.DateParseHandling = reader.DateParseHandling;
clonedReader.DateTimeZoneHandling = reader.DateTimeZoneHandling;
clonedReader.FloatParseHandling = reader.FloatParseHandling;
clonedReader.MaxDepth = reader.MaxDepth;
return clonedReader;
}
private object PopulateLineInfo(JsonLineInfo lineInfoObject, int lineNumber, int linePosition, JObject rawJObject)
{
if (lineInfoObject != null)
{
lineInfoObject.PropertyLineInfos = new Dictionary<string, LineInfo>(StringComparer.InvariantCultureIgnoreCase);
lineInfoObject.LineNumber = lineNumber;
lineInfoObject.LinePosition = linePosition;
foreach (var property in rawJObject.Properties().CoalesceEnumerable())
{
var propertyLineInfo = property as IJsonLineInfo;
if (propertyLineInfo != null)
{
lineInfoObject.PropertyLineInfos.Add(
property.Name,
new LineInfo
{
LineNumber = propertyLineInfo.LineNumber,
LinePosition = propertyLineInfo.LinePosition
});
}
}
}
return lineInfoObject;
}
}
公共类LineInfo
{
[JsonIgnore]
公共整数行号{get;set;}
[JsonIgnore]
public int LinePosition{get;set;}
}
公共抽象类JsonLineInfo:LineInfo
{
[JsonIgnore]
公共字典PropertyLineInfo{get;set;}
}
类LineNumberConverter:JsonConverter
{
公共覆盖布尔可写
{
获取{return false;}
}
公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
{
抛出新的NotImplementedException(“转换器不可写。不应调用方法”);
}
公共覆盖布尔CanConvert(类型objectType)
{
返回typeof(JsonLineInfo).IsAssignableFrom(objectType);
}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
if(reader.TokenType!=JsonToken.Null)
{
int lineNumber=0;
int linePosition=0;
var jsonLineInfo=读卡器为IJsonLineInfo;
if(jsonLineInfo!=null&&jsonLineInfo.HasLineInfo())
{
lineNumber=jsonLineInfo.lineNumber;
linePosition=jsonLineInfo.linePosition;
}
var rawJObject=JObject.Load(读卡器);
var lineInfoObject=Activator.CreateInstance(objectType)作为JsonLineInfo;
填充(this.CloneReader(reader,rawJObject),lineInfoObject);
返回此.PopulateLineInfo(
lineInfoObject:lineInfoObject,
行号:行号,
linePosition:linePosition,
rawJObject:rawJObject);
}
返回null;
}
私有JsonReader CloneReader(JsonReader,JObject-JObject)
{
var clonedReader=jobject.CreateReader();
clonedReader.Culture=reader.Culture;
clonedReader.DateParseHandling=reader.DateParseHandling;
clonedReader.DateTimeZoneHandling=reader.DateTimeZoneHandling;
clonedReader.FloatParseHandling=reader.FloatParseHandling;
clonedReader.MaxDepth=reader.MaxDepth;
返回克隆阅读器;
}
私有对象PopulateLineInfo(JsonLineInfo lineInfoObject、int lineNumber、int linePosition、JObject rawJObject)
{
if(lineInfoObject!=null)
{
lineInfoObject.propertylineinfo=新字典(StringComparer.InvariantCultureInogoreCase);
lineInfoObject.LineNumber=LineNumber;
lineInfoObject.LinePosition=LinePosition;
foreach(rawJObject.Properties().CoalesceEnumerable()中的var属性)
{
var propertyLineInfo=属性为IJsonLineInfo;
if(propertyLineInfo!=null)
{
lineInfoObject.PropertyLineInfo.Add(
property.Name,
新线路信息
{
LineNumber=propertyLineInfo.LineNumber,
LinePosition=propertyLineInfo.LinePosition
});
}
}
}
返回lineInfoObject;
}
}
您说这不是针对反序列化过程中发生的错误,而是说希望在反序列化过程中填充LineNumber
和LinePosition
。您试图准确捕获哪些错误?例如,如果上面示例中的Prop1是一个数据库名称,但数据库不存在(这是一个运行时检查),我希望能够抛出一个异常,并显示消息“Prop1位于第2行,位置10不存在”。这将对使用大型json模板的客户有很大帮助。我正在尝试使用json.Net获取反序列化对象的行号。我尝试了您的方法,但遇到了有关“CoalesceEnumerable()”方法的语法错误。使用blog必须写入哪个名称空间?另外,我可以请您给出一个“ReadJson”方法调用的示例吗?谢谢。@SerkanYılmaz您可以尝试这个简单的扩展:使用System.Collections.Generic;公共静态类IEnumerableExtensions{公共静态IEnumerable CoalesceEnumerable(此IEnumerable源){返回so