C# 一个简陋轻便的Json字符串拼接类
有的时候我们要以Json格式的形式传递参数,用模型或匿名类传给json库转的话,感觉很浪费,但是自己手动拼的话有比较麻烦,因此封装了一个拼接类,非常简陋
2024-8-14 改进版,支持了布尔、子对象和数组等类型
JsonStringBuilder

/// <summary> /// Json字符串建造者,一般用于构建简单的json字符串 /// </summary> public class JsonStringBuilder { readonly StringBuilder sb = new StringBuilder("{"); //不能用char,因为没有char的重载 /// <summary> /// 附加一个需要用双引号引起来的元素,比如key和文本val /// </summary> void AppendTextElement(string val) { //sb.Append("\"" + val + "\""); sb.Append('"'); //这里逐个附加字符,比附加字符串性能更好 sb.Append(val); sb.Append('"'); } /// <summary> /// 附加一个值为字符串类型的键值对 /// </summary> public JsonStringBuilder Append(string key, string val) { if (val == null) { AppendNull(key); } else { AppendTextElement(key); sb.Append(':'); AppendTextElement(val); sb.Append(','); } return this; } /// <summary> /// 附加一个值为日期类型的键值对 /// </summary> public JsonStringBuilder Append(string key, DateTime val) { return Append(key, val.ToString()); } /// <summary> /// 附加一个值为布尔类型的键值对 /// </summary> public JsonStringBuilder Append(string key, bool val) { AppendTextElement(key); sb.Append(':'); sb.Append(val ? "true" : "false"); sb.Append(','); return this; } /// <summary> /// 附加一个值为数值类型的键值对 /// </summary> public JsonStringBuilder Append<T>(string key, T val) where T : struct { AppendTextElement(key); sb.Append(':'); sb.Append(val); sb.Append(','); return this; } /// <summary> /// 附加一个值为引用对象的键值对,不通过委托传递val是为了操作起来更灵活,因为不是所有的数据都被封装成了对象 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="key">键</param> /// <param name="val">对象,用来判断对象是否为空</param> /// <param name="objectAppend">附加对象中的键值对操作</param> /// <returns></returns> public JsonStringBuilder Append<T>(string key, T val, Action<JsonStringBuilder> objectAppend) where T : class { if (val == null) { AppendNull(key); } else { AppendTextElement(key); sb.Append(':'); sb.Append('{'); objectAppend(this); AppendObjectEnd(); } return this; } /// <summary> /// 附加子对象的结束操作,即子对象结束后,拼接一个"}," /// </summary> void AppendObjectEnd() { var end = sb[sb.Length - 1]; if (end == ',') { sb[sb.Length - 1] = '}'; } else { sb.Append('}'); } sb.Append(','); } /// <summary> /// 附件一个值为null的键值对 /// </summary> public JsonStringBuilder AppendNull(string key) { AppendTextElement(key); sb.Append(':'); sb.Append('n'); sb.Append('u'); sb.Append('l'); sb.Append('l'); sb.Append(','); return this; } /// <summary> /// 开始拼接数组 /// </summary> void AppendArrayStart(string key) { AppendTextElement(key); sb.Append(':'); sb.Append('['); } /// <summary> /// 结束拼接数组 /// </summary> void AppendArrayEnd() { var end = sb[sb.Length - 1]; if (end == ',') { sb[sb.Length - 1] = ']'; } else { sb.Append(']'); } sb.Append(','); } /// <summary> /// 附加一个值为字符串集合的键值对 /// </summary> public JsonStringBuilder AppendArray(string key, IEnumerable<string> val) { if (val == null) { AppendNull(key); } else { AppendArrayStart(key); foreach (var p in val) { AppendTextElement(p); sb.Append(','); } AppendArrayEnd(); } return this; } /// <summary> /// 附件一个值为时间集合的键值对 /// </summary> public JsonStringBuilder AppendArray(string key, IEnumerable<DateTime> val) { if (val == null) { AppendNull(key); } else { AppendArrayStart(key); foreach (var p in val) { AppendTextElement(p.ToString()); sb.Append(','); } AppendArrayEnd(); } return this; } /// <summary> /// 附加一个值为字节数组的键值对,注意,json规则中,如果值是字节数组,就需要把字节数组转成base64字符串 /// </summary> public JsonStringBuilder AppendArray(string key, byte[] val) { if (val == null) { AppendNull(key); } else { Append(key, Convert.ToBase64String(val)); } return this; } /// <summary> /// 附加一个值为布尔集合的键值对 /// </summary> public JsonStringBuilder AppendArray(string key, IEnumerable<bool> val) { if (val == null) { AppendNull(key); } else { AppendArrayStart(key); foreach (var p in val) { sb.Append(p ? "true," : "false,"); } AppendArrayEnd(); } return this; } /// <summary> /// 附加一个值为数值集合的键值对 /// </summary> public JsonStringBuilder AppendArray<T>(string key, IEnumerable<T> val) where T : struct { if (val == null) { AppendNull(key); } else { AppendArrayStart(key); sb.Append(string.Join(",", val)); AppendArrayEnd(); } return this; } /// <summary> /// 附加一个值为泛型对象集合的键值对 /// </summary> /// <param name="key">键</param> /// <param name="val">泛型对象集合</param> /// <param name="objectAppend">对单以对象的附加操作</param> /// <returns>当前操作的json构建者对象</returns> public JsonStringBuilder AppendArray<T>(string key, IEnumerable<T> val, Action<JsonStringBuilder, T> objectAppend) where T : class { if (val == null) { AppendNull(key); } else { AppendArrayStart(key); foreach (var p in val) { sb.Append('{'); //这个地方有些特殊,不能直接用AppendArrayStart objectAppend(this, p); AppendObjectEnd(); } AppendArrayEnd(); } return this; } /// <summary> /// 得到json字符串 /// </summary> public override string ToString() { sb[sb.Length - 1] = '}'; return sb.ToString(); ; } /// <summary> /// 重置以作复用 /// </summary> public void Reset() { sb.Clear(); sb.Append('{'); } }
测试代码

public void Test() { /* * 一般用于比较简单的使用场景,不使用模型或者匿名类通过第三方库转,自己自己拼接, * 性能是Newtonsoft.Json的2-3倍 * */ var json = new JsonStringBuilder() .Append("errcode", 1001) .Append("errmsg", "ok") .Append("msgid", 1).ToString(); Console.WriteLine(json); /* * 目前也支持子对象和数组了,如果数据结构很复杂,还是建议使用Newtonsoft.Json, * 因为手动拼接太繁琐了 * */ var user = CreateUser(); var json_jsb = ByJsb(user); var json_newtonsoft = ByNewtonsoft(user); Console.WriteLine(json_jsb); Console.WriteLine(json_newtonsoft); Console.WriteLine(json_jsb == json_newtonsoft); //使用Newtonsoft.Json对比数据完全一致 }
和Newtonsoft.Json对比数据的一致性

class User { public int ID; public string Name; public ushort Age; public bool Married; public byte[] Photo; public User Father; public List<User> Friends; public bool[] TaskState; public List<DateTime> TaskTime; public List<string> TaskDesc; public int[] TaskGrade; public DateTime RecordTime; } /// <summary> /// 创建测试数据 /// </summary> User CreateUser() { User user; user = new User() { ID = 1, Name = "张三", Age = 18, Married = false, Photo = new byte[10], Father = new User { ID = 6, Name = "张大山", RecordTime = DateTime.Now, }, Friends = new List<User>{ new User{ ID = 2, Name = "李四", RecordTime = DateTime.Now, }, new User{ ID =3, Name = "王五", RecordTime = DateTime.Now, } }, TaskState = new bool[10], TaskTime = new List<DateTime>(), TaskDesc = new List<string>(), TaskGrade = new int[10], RecordTime = DateTime.Now, }; new Random().NextBytes(user.Photo); for (int i = 0; i < 10; i++) { user.TaskState[i] = i % 2 == 0; user.TaskTime.Add(DateTime.Now.AddDays(-i)); user.TaskDesc.Add(Guid.NewGuid().ToString()); user.TaskGrade[i] = i; } return user; } string ByNewtonsoft(User user) { return JsonHelper.GetJson(user); } string ByJsb(User user) { return BuildUserJson(new JsonStringBuilder(), user).ToString(); } JsonStringBuilder BuildUserJson(JsonStringBuilder jb, User user) { return jb.Append("ID", user.ID) .Append("Name", user.Name) .Append("Age", user.Age) .Append("Married", user.Married) .AppendArray("Photo", user.Photo) .Append("Father", user.Father, p => { BuildUserJson(p, user.Father); }).AppendArray("Friends", user.Friends, (p, val) => { BuildUserJson(p, val); }).AppendArray("TaskState", user.TaskState) .AppendArray("TaskTime", user.TaskTime) .AppendArray("TaskDesc", user.TaskDesc) .AppendArray("TaskGrade", user.TaskGrade) .Append("RecordTime", user.RecordTime); } }
之前的旧版本(功能非常简单)

using System; using System.Text; namespace ConsoleApp { /// <summary> /// 简单的json字符串构建类,只支持单层基础类型字段,不支持数组,对象等字段 /// </summary> public class JsonStringBuilder { readonly StringBuilder sb = new StringBuilder("{"); public void Append(string key, string val, bool hasMark) { if (hasMark) { sb.Append($"\"{key}\":\"{val}\","); } else { sb.Append($"\"{key}\":{val},"); } } public void Append(string key, string val) { Append(key, val, true); } public void Append(string key, DateTime val) { Append(key, val.ToString(), true); } public void Append<T>(string key, T val) where T : struct { Append(key, val.ToString(), false); } public override string ToString() { sb[sb.Length - 1] = '}'; string json = sb.ToString(); sb[sb.Length - 1] = ','; //不破坏原字符组,因为可能会继续Append return json; } } }
测试代码

static void Test() { int id = 1; string name = "张三"; DateTime birthDate = new DateTime(1989, 6, 8); //一些比较简单的json结构没必要使用模型或者匿名类通过json库进行转换 SpeedTester.Start(5, () => { //一个速度测试函数,用来对比自己拼和封装拼接的运行速度差距 //但是手动拼比较麻烦,特别是双引号,处理器起来很麻烦,但是性能最好 string json = "{\"ID\":" + id + ",\"Name\":\"" + name + "\",\"BirthDate\":\"" + birthDate + "\"}"; }, () => { //稍微封装一下,这样就不用关系双引号的问题了,性能也比json库快很多 JsonStringBuilder jsb = new JsonStringBuilder(); jsb.Append("ID", id); jsb.Append("Name", name); jsb.Append("BirthDate", birthDate); string json = jsb.ToString(); Log.Info(json); }); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?