C# 带Body的GET请求硬编码JSON正常但序列化对象失效问题
问题原因
- 首先GET请求携带请求体本身属于不符合HTTP规范的hack实现,你通过反射修改
ContentBodyNotAllowed内部字段的逻辑本身稳定性极低,不同.NET版本的内部类结构、字段名可能存在差异,这是底层的隐患。 - 序列化得到的JSON与硬编码JSON存在隐性差异:
- 可先打印两个场景下传入
CallHttpGet的JSON字符串做对比,Newtonsoft默认序列化可能会输出多余的空格、换行,或者如果实体类新增了未加[JsonIgnore]的字段也会被一同序列化,导致服务端解析JSON失败。 - 另一个高频触发原因:你当前代码中使用的
StreamWriter默认是带BOM(字节顺序标记)的UTF-8编码,硬编码的JSON本身不带BOM,部分严格的服务端会把BOM识别为无效字符,直接抛出JSON格式错误。
- 可先打印两个场景下传入
- 缺少显式的
Content-Length请求头:硬编码的JSON长度固定,HttpWebRequest可能自动计算了请求体长度,而序列化后的动态JSON没有显式设置长度,部分服务端会因为无法确定请求体大小直接拒收请求。
解决方案
最优方案(根治问题)
将GET请求改为POST请求即可,GET请求带请求体的行为本身就不被绝大多数反向代理、CDN、服务端框架默认支持,修改request.Method = "POST",不需要再做反射修改内部字段的hack操作,兼容性最好。
兼容方案(必须保留带请求体的GET请求时使用)
- 校验序列化结果:在调用接口前打印序列化得到的JSON,和硬编码的JSON对比确保内容完全一致,可给实体类加
[JsonObject(MemberSerialization.OptIn)]注解,只序列化标记了[JsonProperty]的字段,避免多余字段被序列化。 - 调整请求体写入逻辑,使用无BOM的UTF-8编码,同时显式设置Content-Length头:
public string CallHttpGet(string url, string json) { var request = (HttpWebRequest)WebRequest.Create(url); request.Method = "GET"; request.ContentType = "application/json"; request.Headers.Add("Authorization",authorizationKey); request.Headers.Add("X-ng-requestTime", requestTime); var type = request.GetType(); var currentMethod = type.GetProperty("CurrentMethod", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(request); var methodType = currentMethod.GetType(); methodType.GetField("ContentBodyNotAllowed", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(currentMethod, false); // 显式计算请求体字节长度,设置Content-Length byte[] jsonBytes = Encoding.UTF8.GetBytes(json); request.ContentLength = jsonBytes.Length; // 直接写入字节流,避免StreamWriter的BOM问题 using (var stream = request.GetRequestStream()) { stream.Write(jsonBytes, 0, jsonBytes.Length); } var response = (HttpWebResponse)request.GetResponse(); return new StreamReader(response.GetResponseStream()).ReadToEnd(); }
- 序列化时关闭格式化输出,避免多余的空格换行:
var json = JsonConvert.SerializeObject(new MuaDesignationListRequest { DesignationType = "MUAP" }, new JsonSerializerSettings { Formatting = Formatting.None });
内容的提问来源于stack exchange,提问作者TheProgrammer
相关产品推荐
相关产品推荐

