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

JSchemaValidatingReader处理大字符串令牌时内存溢出问题求助

解决Newtonsoft.Json.Schema验证大字符串时的内存占用问题

问题概述

使用Newtonsoft.Json v13.0.3、Newtonsoft.Json.Schema 4.0.1和.NET 9.0.304验证JSON时,当传入含10M字符的demoId字段时,验证错误消息会包含完整的大字符串,经dotMemory检测该字符串在内存中存在4份,占用约80MB内存。需要在不自定义JsonTextReader或核心验证逻辑的前提下优化内存占用。

解决方案

1. 自定义Schema错误消息模板,避免嵌入大字符串

修改JSON Schema,为maxLength规则指定不包含实际字段值的错误提示,替代默认会嵌入完整字符串的消息:

{
    "type": "object",
    "additionalProperties": false,
    "required": [
        "demoId"
    ],
    "properties": {
        "demoId": {
            "type": "string",
            "maxLength": 50,
            "errorMessage": "字段 demoId 长度超过最大限制(50字符)"
        }
    }
}

2. 优化ValidationEventHandler,避免引用大字符串实例

在事件处理逻辑中,不要直接使用默认的a.Message(该消息会包含完整的大字符串),而是通过ValidationError的路径、规则等属性构造轻量错误消息,同时标记错误已处理,避免后续默认逻辑持有大字符串引用:

var validationResult = new Lazy<ReplyErrorReqV1Payload>();
var streamReader = new StreamReader(stream);
var jsonReader = new JsonTextReader(streamReader);
var validatingReader = new JSchemaValidatingReader(jsonReader);
validatingReader.Schema = schema;

bool validationFailed = false;
validatingReader.ValidationEventHandler += (o, a) =>
{
    // 构造不包含大字符串的错误消息
    var errorMsg = $"验证失败:路径[{a.ValidationError.Path}] 违反{a.ValidationError.Rule}规则,{a.ValidationError.Message}";
    Console.WriteLine(errorMsg);
    
    validationFailed = true;
    a.Handled = true; // 标记错误已处理,阻止默认消息生成逻辑
};

// 一旦检测到错误就停止读取,避免加载剩余大字符串
while (!validationFailed && await validatingReader.ReadAsync(cancellationToken))
{
    // 仅驱动读取到错误发生时为止
}

3. 额外优化:提前终止读取流程

当验证错误触发后,立即终止JSON读取流程,避免继续加载剩余的大字符串内容,进一步减少内存占用。上述代码中已经通过validationFailed标记实现了这一点。

原理说明

  • 默认的验证错误消息会将违规字段的完整值嵌入其中,导致大字符串被多次引用(事件参数、消息字符串等),无法被GC及时回收。
  • 通过自定义Schema错误消息和轻量事件处理逻辑,彻底避免对大字符串实例的引用,同时提前终止读取,减少不必要的内存加载。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 13:25:00