入參用 JToken 構造,尤其適合參數結構動態(如不確定字段、嵌套層級變化)或需要靈活拼接的場景。JToken 作為 Json.NET 的核心節點類型,可直接序列化為標準 JSON 字符串。
核心思路
- 用
JObject(JToken的子類,專門處理 JSON 對象)構造請求參數(鍵值對、嵌套結構、數組均可); - 直接將
JObject傳遞給JsonConvert.SerializeObject()(無需手動轉換,Json.NET 會自動序列化為 JSON 字符串); - 後續請求發送邏輯(
HttpWebRequest配置、流寫入)完全複用之前的代碼,無需修改。
完整實現代碼(JToken 構造入參)
using System;
using System.IO;
using System.Net;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq; // 引入 JToken/JObject 命名空間
namespace Net20PostJsonWithJTokenParam
{
class Program
{
static void Main(string[] args)
{
// 忽略 HTTPS 證書驗證(僅測試環境)
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
string apiUrl = "https://api.example.com/your-endpoint"; // 替換為實際接口地址
try
{
// 1. 核心步驟:用 JObject(JToken 子類)構造入參
JObject requestParams = new JObject();
// 添加基礎字段(字符串、數值、布爾類型)
requestParams["username"] = "張三"; // 字符串
requestParams["age"] = 28; // 數值(自動序列化為無引號)
requestParams["isVip"] = true; // 布爾(自動序列化為無引號)
requestParams["logContent"] = "測試日誌內容"; // 字符串
// 添加嵌套結構(如 address 嵌套對象)
JObject address = new JObject();
address["province"] = "廣東省";
address["city"] = "廣州市";
requestParams["address"] = address; // 嵌套 JObject
// 添加數組(如 hobbies 數組)
JArray hobbies = new JArray("編程", "籃球", "旅遊"); // 直接初始化數組
requestParams["hobbies"] = hobbies; // 數組字段
// 動態添加/刪除字段(靈活調整參數)
requestParams["gender"] = "男"; // 動態添加
// requestParams.Remove("gender"); // 按需刪除字段
// 2. 序列化 JObject 為 JSON 字符串(Json.NET 自動處理格式)
string jsonData = JsonConvert.SerializeObject(requestParams, Formatting.Indented);
Console.WriteLine("請求 JSON 數據:\n" + jsonData);
// 3. 發送 POST 請求
string responseJson = SendPostJsonRequest(apiUrl, jsonData);
Console.WriteLine("\n響應原始 JSON:" + responseJson);
// 4. 解析響應(複用 JToken 方式判斷 code == "200")
JToken responseToken = JToken.Parse(responseJson);
if (responseToken.Value<string>("code") == "200")
{
Console.WriteLine("請求成功!提示:" + responseToken["msg"]);
}
else
{
Console.WriteLine("請求失敗!");
}
}
catch (JsonReaderException ex)
{
Console.WriteLine("JSON 解析異常:" + ex.Message);
}
catch (Exception ex)
{
Console.WriteLine("請求異常:" + ex.Message);
}
}
/// <summary>
/// POST 請求核心方法
/// </summary>
private static string SendPostJsonRequest(string url, string jsonData)
{
if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(jsonData))
throw new ArgumentNullException("請求地址或參數不能為空");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/json; charset=utf-8";
request.Timeout = 10000; // 10秒超時
// 寫入請求體
byte[] postBytes = Encoding.UTF8.GetBytes(jsonData);
request.ContentLength = postBytes.Length; // .NET 2.0 必須設置長度
using (Stream requestStream = request.GetRequestStream())
{
requestStream.Write(postBytes, 0, postBytes.Length);
requestStream.Flush();
}
// 讀取響應
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8))
{
return reader.ReadToEnd();
}
}
}
}
}
JToken 構造入參的核心用法
1. 基礎字段構造(JObject)
JObject 對應 JSON 對象({}),通過索引器直接添加鍵值對,自動適配類型:
JObject requestParams = new JObject();
requestParams["key1"] = "字符串值"; // 序列化後:"key1":"字符串值"
requestParams["key2"] = 123; // 序列化後:"key2":123
requestParams["key3"] = true; // 序列化後:"key3":true
requestParams["key4"] = null; // 序列化後:"key4":null
2. 嵌套對象構造(JObject 嵌套)
適合參數包含子對象(如 address: {province: "廣東", city: "廣州"}):
JObject address = new JObject();
address["province"] = "廣東省";
address["city"] = "廣州市";
requestParams["address"] = address; // 嵌套後序列化:"address":{"province":"廣東省","city":"廣州市"}
3. 數組構造(JArray)
JArray 對應 JSON 數組([]),支持直接初始化或動態添加元素:
// 方式1:直接初始化
JArray hobbies = new JArray("編程", "籃球", "旅遊");
requestParams["hobbies"] = hobbies; // 序列化後:"hobbies":["編程","籃球","旅遊"]
// 方式2:動態添加元素
JArray tags = new JArray();
tags.Add("測試");
tags.Add("日誌");
requestParams["tags"] = tags; // 序列化後:"tags":["測試","日誌"]
4. 動態調整參數
支持運行時添加/刪除/修改字段,靈活性拉滿:
// 添加字段
requestParams["newKey"] = "新值";
// 修改字段
requestParams["age"] = 29; // 覆蓋原有值
// 刪除字段
requestParams.Remove("isVip"); // 移除不需要的參數
5. 序列化(直接序列化 JObject)
無需手動轉換,JsonConvert.SerializeObject() 可直接將 JObject/JToken 序列化為標準 JSON 字符串:
JObject requestParams = new JObject();
requestParams["username"] = "張三";
string jsonData = JsonConvert.SerializeObject(requestParams);
// 結果:{"username":"張三"}
JToken 構造入參的優缺點
優點
- 極致靈活:支持動態添加/刪除/修改參數,適合字段不固定、嵌套結構多變的場景;
- 類型自動適配:數值、布爾、字符串類型自動序列化(無需手動拼接引號,避免格式錯誤);
- 支持複雜結構:輕鬆處理嵌套對象、數組,比
Dictionary更直觀(無需Dictionary<string, object>嵌套); - 無縫銜接:直接序列化
JObject,無需中間轉換,與現有請求流程完全兼容。
缺點
- 無編譯時校驗:鍵名拼寫錯誤(如
requestParams["userName"]而非requestParams["username"])只能運行時發現; - 代碼略顯繁瑣:簡單鍵值對場景下,比
Dictionary或實體類多幾行代碼; - 依賴 Json.NET:必須引入 Newtonsoft.Json(但你已在使用,無額外成本)。
關鍵注意事項
- Json.NET 版本兼容:確保使用 Newtonsoft.Json 12.0.3 及以下版本(.NET 2.0 不支持更高版本);
- 參數類型匹配:接口要求的字段類型需與
JObject中添加的類型一致(如接口要求age是數值,就不能用字符串requestParams["age"] = "28"); - 空值處理:若接口不允許
null值,需避免添加requestParams["key"] = null,或在序列化時忽略空值:// 序列化時忽略空值字段(可選) JsonSerializerSettings settings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }; string jsonData = JsonConvert.SerializeObject(requestParams, settings); - 數組元素類型:
JArray中可混合類型(如new JArray("a", 1, true)),但需符合接口要求,避免序列化後格式不兼容。
入參構造方式對比(彙總)
| 入參構造方式 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| 手動拼接 JSON | 無需依賴,原生支持 | 易出錯,不支持複雜結構 | 極簡參數,無依賴場景 |
| Dictionary | 無需實體類,簡單直觀 | 嵌套/數組需手動處理類型 | 簡單鍵值對,無複雜結構 |
| 實體類 | 類型安全,編譯時校驗 | 不支持動態字段,需提前定義 | 字段固定,長期維護 |
| JToken(JObject) | 動態靈活,支持複雜結構,類型自動適配 | 無編譯時校驗,依賴 Json.NET | 動態字段、嵌套/數組結構,推薦 |