You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

开发JSON Diff工具:如何获取目标JSON片段在原字符串的索引与长度?

解决JSON Token在原字符串中精准定位的方案

核心问题在于不能依赖JToken序列化后的字符串匹配原JSON(序列化会丢失原缩进、换行等格式),而是要直接通过解析时保留的位置信息来定位目标片段。以下是具体实现步骤:

1. 解析JSON时保留行位置信息

Newtonsoft.Json支持在解析时记录每个Token的行号和列号,通过JsonLoadSettings开启该功能:

var loadSettings = new JsonLoadSettings
{
    LineInfoHandling = LineInfoHandling.Load
};
JObject jsonObj = JObject.Parse(originalJsonStr, loadSettings);

2. 获取目标Token的行号与列号

通过SelectToken拿到目标Token后,转换为ILineInfo接口提取位置数据:

JToken targetToken = jsonObj.SelectToken("a[0]");
if (targetToken is not ILineInfo lineInfo)
{
    // 处理未获取到位置信息的异常情况
    return;
}
int startLine = lineInfo.LineNumber;
int startColumn = lineInfo.LinePosition;

3. 转换行号列号为原字符串起始索引

遍历原JSON字符串,统计换行符找到目标行,再根据列号定位起始位置:

int startIndex = 0;
int currentLine = 1;
foreach (char c in originalJsonStr)
{
    if (currentLine == startLine)
    {
        // 列号从1开始计数,需减1转为0索引
        startIndex += startColumn - 1;
        break;
    }
    if (c == '\n')
    {
        currentLine++;
    }
    startIndex++;
}

4. 计算目标Token的长度

使用JsonTextReader读取原JSON,定位到目标Token后跟踪到其结束位置,计算总长度:

int tokenLength = 0;
using (var stringReader = new StringReader(originalJsonStr))
using (var jsonReader = new JsonTextReader(stringReader))
{
    // 定位到目标Token的起始位置
    while (jsonReader.Read())
    {
        if (jsonReader is ILineInfo readerLineInfo &&
            readerLineInfo.LineNumber == startLine &&
            readerLineInfo.LinePosition == startColumn)
        {
            int tokenStart = jsonReader.TokenStartIndex;
            int originalDepth = jsonReader.Depth;
            JsonToken startTokenType = jsonReader.TokenType;

            // 读取直到Token结束(对象对应EndObject,数组对应EndArray)
            while (jsonReader.Read())
            {
                if (jsonReader.Depth == originalDepth && 
                    (startTokenType == JsonToken.StartObject && jsonReader.TokenType == JsonToken.EndObject ||
                     startTokenType == JsonToken.StartArray && jsonReader.TokenType == JsonToken.EndArray))
                {
                    // 结束位置为结束标记的索引+1(包含}或]字符)
                    int tokenEnd = jsonReader.TokenStartIndex + 1;
                    tokenLength = tokenEnd - tokenStart;
                    break;
                }
            }
            break;
        }
    }
}

5. 在RichTextBox中选中片段

拿到startIndex和tokenLength后,直接调用控件的选中方法:

richTextBox1.SelectionStart = startIndex;
richTextBox1.SelectionLength = tokenLength;

注意事项

  • 若原JSON使用\r\n作为换行符,统计行号时需额外判断\r,避免行号计数错误。
  • 对于字符串、数字等简单Token,无需跟踪到EndObject/EndArray,直接通过jsonReader.TokenStartIndex和后续字符位置计算长度即可。

内容的提问来源于stack exchange,提问作者rhobaj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 18:40:09