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

JSON-RPC调用报400错误及NaN值问题排查求助

解决JSON-RPC响应序列化失败(错误/NaN结果)的问题

根据你描述的情况——运行指定源码时返回错误或NaN,手动构造响应类序列化仍无法得到期望的JSON结构,我梳理了几个常见的问题点和对应的解决方法,都是基于JsonRpc命名空间下的场景:

1. 先处理JSON不支持的NaN值

JSON规范本身并不支持NaN、Infinity这类特殊数值,多数序列化库(比如System.Text.Json、Newtonsoft.Json)遇到这些值时会直接抛出异常,或者输出不符合要求的内容,这是最常见的序列化失败原因。

解决方法:在计算result前先检查并替换特殊值,或者配置序列化器自动处理:

示例(System.Text.Json)

在JsonRpc命名空间下配置序列化选项,并添加自定义转换器处理NaN:

namespace JsonRpc
{
    public static class RpcSerializer
    {
        public static JsonSerializerOptions GetOptions()
        {
            var options = new JsonSerializerOptions();
            options.Converters.Add(new NaNToNullConverter());
            return options;
        }
    }

    // 自定义转换器:将NaN/Infinity转换为null
    public class NaNToNullConverter : JsonConverter<double>
    {
        public override double Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            return reader.GetDouble();
        }

        public override void Write(Utf8JsonWriter writer, double value, JsonSerializerOptions options)
        {
            if (double.IsNaN(value) || double.IsInfinity(value))
            {
                writer.WriteNullValue();
            }
            else
            {
                writer.WriteNumberValue(value);
            }
        }
    }
}

示例(Newtonsoft.Json)

namespace JsonRpc
{
    public static class RpcSerializer
    {
        public static JsonSerializerSettings GetSettings()
        {
            return new JsonSerializerSettings
            {
                Converters = new List<JsonConverter> { new NaNConverter() },
                NullValueHandling = NullValueHandling.Ignore
            };
        }
    }

    public class NaNConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(double) || objectType == typeof(float);
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            return reader.Value;
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (value is double d && (double.IsNaN(d) || double.IsInfinity(d)))
            {
                writer.WriteNull();
            }
            else if (value is float f && (float.IsNaN(f) || float.IsInfinity(f)))
            {
                writer.WriteNull();
            }
            else
            {
                writer.WriteValue(value);
            }
        }
    }
}

2. 检查手动构造的响应类是否符合序列化要求

确保你的响应类属性权限、名称和期望的JSON结构完全匹配:

namespace JsonRpc
{
    // 类和属性必须是public,序列化器才能访问
    public class RpcResponse
    {
        // 用JsonPropertyName指定JSON字段名,避免大小写不匹配问题
        [JsonPropertyName("id")]
        public int Id { get; set; }

        [JsonPropertyName("status")]
        public string Status { get; set; }

        [JsonPropertyName("type")]
        public string Type { get; set; }

        [JsonPropertyName("result")]
        public object Result { get; set; }

        // 构造函数快速初始化默认值
        public RpcResponse(int requestId)
        {
            Id = requestId;
            Status = "success";
            Type = "response";
            Result = new {}; // 默认空对象
        }
    }
}

3. 统一错误捕获与响应构造

运行指定源码时可能抛出异常,导致无法正常构造响应。需要在执行逻辑外层添加try-catch,确保无论成功还是失败都返回符合格式的JSON:

namespace JsonRpc
{
    public class RpcHandler
    {
        public string ExecuteSourceCode(int requestId, string sourceCode)
        {
            try
            {
                // 执行源码逻辑
                var rawResult = RunUserSourceCode(sourceCode);
                // 清理结果中的特殊值
                var cleanedResult = CleanSpecialValues(rawResult);
                
                // 构造成功响应
                var response = new RpcResponse(requestId) { Result = cleanedResult };
                return JsonSerializer.Serialize(response, RpcSerializer.GetOptions());
            }
            catch (Exception ex)
            {
                // 构造错误响应(可根据需求调整错误内容)
                var errorResponse = new RpcResponse(requestId)
                {
                    Status = "error",
                    Result = new { errorMessage = ex.Message }
                };
                return JsonSerializer.Serialize(errorResponse, RpcSerializer.GetOptions());
            }
        }

        private object RunUserSourceCode(string sourceCode)
        {
            // 你的源码执行逻辑
        }

        private object CleanSpecialValues(object result)
        {
            // 递归遍历结果,替换所有NaN/Infinity为合法值(比如null)
            // 针对字典、列表等复杂类型需要单独处理
        }
    }
}

4. 验证序列化输出

如果还是有问题,可以先将响应对象序列化后打印,检查格式是否符合预期:

var testResponse = new RpcResponse(1);
var json = JsonSerializer.Serialize(testResponse, RpcSerializer.GetOptions());
Console.WriteLine(json);
// 检查输出是否为:{"id":1,"status":"success","type":"response","result":{}}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:26:53