JSTree无法从JSON数组正常加载,单字符串返回正常数组模式失效
问题:jstree将C#返回的数组解析为纯文本节点
我尝试解决该问题多日但未果:
- 返回单个JSON字符串时,jstree能正常渲染节点
- 但将节点添加到List/数组返回时,jstree把每个JSON字符串当作纯文本显示,无法解析字段
弹窗验证的数据格式看似正确,但实际渲染后每个节点都是纯文本JSON字符串(浏览器元素检查结果可见)。
错误核心原因
- C#端返回的是字符串数组而非对象数组:手动拼接的JSON字符串存入数组后,WebMethod序列化结果是
["{...}","{...}"],前端拿到的是字符串集合,jstree直接把每个字符串当作节点文本,不会解析为JSON对象。 - 前端未正确传递节点数据:原JS代码的success函数仅alert结果,未将处理后的对象数组返回给jstree。
- SQL存在注入风险:原代码直接拼接SQL参数,属于不安全写法。
修复方案
步骤1:C#端改用实体类返回对象数组
不再手动拼接JSON,创建节点实体类让WebMethod自动序列化:
1.1 定义节点实体类
public class JsTreeNode { public string id { get; set; } public string parent { get; set; } public string text { get; set; } public string type { get; set; } public string value { get; set; } }
1.2 修改WebMethod代码
[WebMethod] public static List<JsTreeNode> getChildren(string libraryID) { List<JsTreeNode> documentList = new List<JsTreeNode>(); // 使用using自动释放数据库资源 using(SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString)) { con.Open(); // 获取根节点名称(参数化查询防注入) string getUserInfo = "select LibraryName from Document_Library_Names where Id = @LibraryID"; SqlCommand getUserInfocmd = new SqlCommand(getUserInfo, con); getUserInfocmd.Parameters.AddWithValue("@LibraryID", libraryID); string libraryName = Convert.ToString(getUserInfocmd.ExecuteScalar()).Trim(); // 添加根节点对象 documentList.Add(new JsTreeNode { id = libraryName, parent = "#", text = libraryName, type = "FDR", value = "0" }); // 获取文档列表(参数化查询) string strGetDocuments = "Select * from Documents where LID = @LibraryID order by DisplayOrder ASC"; SqlCommand getDocumentsCMD = new SqlCommand(strGetDocuments, con); getDocumentsCMD.Parameters.AddWithValue("@LibraryID", libraryID); DataTable dt = new DataTable(); using(SqlDataReader sqlDR = getDocumentsCMD.ExecuteReader()) { dt.Load(sqlDR); } if(dt.Rows.Count > 0) { foreach(DataRow row in dt.Rows) { string ID = row[0].ToString().Trim(); string name = row[3].ToString().Trim(); string parentFolder = row[4].ToString().Trim(); string displayOrder = row[5].ToString().Trim(); string extension = row[8].ToString().Trim(); string parentFolderID = libraryName; // 默认父节点为根 if(!string.IsNullOrEmpty(parentFolder)) { // 查询父文件夹ID(参数化查询) string strParentFolderID = "Select ID from Documents where Name=@Name and Type=0"; using(SqlCommand strParentFolderIDcmd = new SqlCommand(strParentFolderID, con)) { strParentFolderIDcmd.Parameters.AddWithValue("@Name", parentFolder); object result = strParentFolderIDcmd.ExecuteScalar(); if(result != null) { parentFolderID = result.ToString(); } } } // 添加子节点对象 documentList.Add(new JsTreeNode { id = ID, parent = parentFolderID, text = name, type = extension, value = displayOrder }); } } } return documentList; }
步骤2:修改前端JS代码,正确传递节点数据
调整jstree的data配置,确保将WebMethod返回的对象数组传给jstree:
<script src="Scripts/jquery-3.6.1.js"></script> <script src="Scripts/jstree.js"></script> <link href="Scripts/themes/default/style.css" rel="stylesheet" /> <div id="libraryTreeview"></div> <script type="text/javascript"> const queryString = window.location.search; const urlParams = new URLSearchParams(queryString); const libraryID = urlParams.get('ID'); $('#libraryTreeview').jstree({ "core": { "data": function (node, cb) { $.ajax({ type: "POST", url: "LibraryFiles.aspx/getChildren", data: JSON.stringify({ libraryID: libraryID }), contentType: "application/json; charset=utf-8", dataType: "json", success: function (results) { // 将返回的对象数组传给jstree cb(results.d); } }); }, "themes": { dots: false, "variant": "large", "responsive": true } } }); </script>
修复后说明
- C#端返回的是
List<JsTreeNode>,WebMethod会自动序列化为JSON对象数组[{"id":"...",...}, {...}] - 前端拿到对象数组后,jstree可以正确识别每个节点的id、parent、text等属性,渲染出正常的树形结构
- 同时修复了SQL注入风险,代码更安全可靠
内容的提问来源于stack exchange,提问作者TimEdwards
相关产品推荐
相关产品推荐

