Newtonsoft.Json-反序列化为JObject时获取相应的行号

问题描述

我正在反序列化基于json-ld的json以针对诸如schema.org之类的内容进行验证。因此,我无法反序列化为已知的对象类型,所以我将通用反序列化为JObject。

如果遇到错误(例如不受支持属性),我想参考源代码。例如行号可以列位置。

我以为我在这里得到了答案:

Newtonsoft.Json - Getting corresponding line numbers of deserialized objects from JSON for better error handling

但是反序列化到JObject时不起作用。 ReadJson没有被调用

反序列化为JObject时有什么方法获取位置信息吗?

var lineNumberConverter = new LineNumberConverter();

var json = JsonConvert.DeserializeObject(jsonLdScript.TextContent,new JsonSerializerSettings()
  {
    Converters = new[] { lineNumberConverter }
  });

    public class JsonPosition
    {
        public int StartLine { get; set; }
        public int StartColumn { get; set; }

        public int EndLine { get; set; }
        public int EndColumn { get; set; }
    }

    public class LineNumberConverter : JsonConverter
    {
        public Dictionary<object,JsonPosition> Positions = new Dictionary<object,JsonPosition>();
        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 true;
        }
        public override object ReadJson(JsonReader reader,Type objectType,object existingValue,JsonSerializer serializer)
        {
            JsonPosition position = null;

            var jsonLineInfo = reader as IJsonLineInfo;

            if (reader.TokenType != JsonToken.Null)
            {
                if (jsonLineInfo != null && jsonLineInfo.HasLineInfo())
                {
                    position = new JsonPosition() { StartLine = jsonLineInfo.LineNumber,StartColumn = jsonLineInfo.LinePosition };
                }
            }

            var jObject = JObject.Load(reader);

            if (position != null)
            {
                if (jsonLineInfo != null && jsonLineInfo.HasLineInfo())
                {
                    position.EndLine = jsonLineInfo.LineNumber;
                    position.EndColumn = jsonLineInfo.LinePosition;
                    Positions.Add(jObject,position);
                }
            }

            return jObject;
        }
    }

解决方法

我现在正在使用JsonTextReader,它设置起来比较复杂,但可以满足我的需求。 reader对象包含当前位置信息,这意味着当它通过json读取时,我可以获得每个令牌的位置。在阅读之前和之后进行检查,我会看到突出显示的文本范围。