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

如何用TypeBox解析HTTP请求?解决循环结构JSON转换错误

TypeBox验证请求对象时的循环引用问题解决

问题场景

使用TypeBox验证整个Express Request对象时触发循环引用错误,但单独验证request.body或request.params可正常工作。

出错代码

import { Type } from '@sinclair/typebox';
import { Value } from '@sinclair/typebox/value';

const metaReqSchema = Type.Object({
  name: Type.String()
});
const reqSchema = Type.Object({
  params: Type.Object({
    idParam: Type.String()
  }),
  body: metaReqSchema
});
@httpPost('/version/:idParam')
public async getMeta(request: Request, response: Response, next: NextFunction) {
  try {
    const dataInputValidated = Value.Decode(reqSchema, request);

    console.log('验证后的输入', dataInputValidated.body);
    console.log('参数', dataInputValidated.params);

    return response.status(200).json({
      data: 1
    });
  } catch (err) {
    return response.status(500).json({
      data: err
    });
  }
}

错误信息

Converting circular structure to JSON
    --> starting at object with constructor 'Socket'
    |     property 'parser' -> object with constructor 'HTTPParser'
    --- property 'socket' closes the circle

正常运行的代码片段

单独验证request.body时能正常工作:

try {
  const dataInputValidated = Value.Decode(metaReqSchema, request.body);

  console.log('验证后的输入', dataInputValidated);
  console.log('参数', dataInputValidated);

  return response.status(200).json({
    data: dataInputValidated
  });
} catch (err) {
  return response.status(500).json({
    error: err
  });
}

问题原因

Express的Request对象包含大量带循环引用的内部属性(如socket、parser等),直接将整个Request对象传入Value.Decode时,TypeBox会保留原对象的所有属性,后续尝试将该对象序列化为JSON返回时,就会触发循环引用错误。同时Value.Decode默认返回原对象的引用,而非仅包含schema定义属性的新对象。

解决方案

方法1:传入仅包含所需属性的纯对象

不要直接传入整个Request对象,构造符合reqSchema结构的纯对象,只包含params和body:

@httpPost('/version/:idParam')
public async getMeta(request: Request, response: Response, next: NextFunction) {
  try {
    const requestData = {
      params: request.params,
      body: request.body
    };
    const dataInputValidated = Value.Decode(reqSchema, requestData);

    console.log('验证后的输入', dataInputValidated.body);
    console.log('参数', dataInputValidated.params);

    return response.status(200).json({
      data: 1
    });
  } catch (err) {
    return response.status(500).json({
      error: err instanceof Error ? err.message : err
    });
  }
}

方法2:使用Value.Encode生成纯净对象

如果需要仅包含schema定义属性的全新对象(而非原对象引用),可以用Value.Encode方法,它会根据schema过滤并生成新对象,彻底避免循环引用:

const requestData = {
  params: request.params,
  body: request.body
};
const dataInputValidated = Value.Encode(reqSchema, requestData);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 13:35:04