使用原生JavaScript解析嵌套字符串对象的问题求助
如何解析嵌套的非标准JSON字符串为JavaScript对象?
我尝试解析一个嵌套字符串对象以返回对应的Object类型数据。例如,给定字符串:
'{dog : cat, joe: { jane: cat, peanut : dog }, fat : skinny}',希望将其转换为Object类型,返回值为:{dog : cat, joe: { jane: cat, peanut : dog }, fat : skinny}。
我先看了你写的代码:
function Parse(string) { if (string[0] == '{' && string[string.length - 1] == '}') { const inObj = string.substring(1, string.length - 1); const arr = inObj.split(','); const keyVal = arr.map(c => c.split(':')); const obj = {}; for (var i = 0; i < keyVal.length; i++) { let ele = keyVal[i]; if (ele[1].startsWith('{')) { let string2 = ele[1]; for (var j = i + 1; i < keyVal.length; i++) { console.log(keyVal[j]); if (keyVal[j].endsWith('}')) { string2 += keyVal[j]; break; } else { string2 += keyVal[j]; } } obj[ele[0]] = JSONParser(string2); } else { obj[ele[0]] = ele[1]; } } return obj; } }
你的思路方向是对的,但有几个关键问题导致代码无法正常工作:
- 直接按逗号分割会破坏嵌套结构:嵌套对象里的逗号会被当成外层键值对的分隔符,导致拆分后的数组元素完全错误。
- 内层循环的索引逻辑混乱:你在内层循环里修改了外层的
i变量,会直接跳过很多外层元素,遍历逻辑彻底出错。 - 忽略了空格处理:原字符串里的空格(比如
dog : cat)会留在键和值里,导致结果不符合预期。 - 函数名不一致:你调用了
JSONParser但定义的函数是Parse,会直接抛出引用错误。
正确的解析思路
解析这类嵌套结构,不能简单用固定字符分割,必须通过追踪括号层级来区分外层和内层的分隔符。具体步骤如下:
- 先清理字符串首尾的空格,校验是否是合法的对象格式(以
{开头、}结尾)。 - 遍历字符串内部内容,用计数器
braceCount记录当前括号的层级:- 遇到
{时计数器+1,遇到}时计数器-1。 - 只有当计数器为0时,遇到的逗号才是外层键值对的分隔点。
- 遇到
- 分割出每个外层键值对后,找到第一个不在嵌套对象内的
:,拆分键和值:- 清理键的前后空格得到键名。
- 如果值以
{开头,递归调用解析函数处理嵌套对象;否则清理空格作为普通值。
修正后的代码
function parseNestedObject(str) { // 清理首尾空格并校验格式 const trimmedStr = str.trim(); if (!trimmedStr.startsWith('{') || !trimmedStr.endsWith('}')) { throw new Error('输入不是有效的对象字符串'); } const content = trimmedStr.slice(1, -1).trim(); const result = {}; let braceCount = 0; let currentKeyStart = 0; let keyValueSeparatorIndex = -1; for (let i = 0; i < content.length; i++) { const char = content[i]; // 追踪括号层级 if (char === '{') braceCount++; if (char === '}') braceCount--; // 仅在括号层级为0时,处理键值分隔符和外层逗号 if (braceCount === 0) { if (char === ':') { keyValueSeparatorIndex = i; } else if (char === ',') { // 提取并处理当前键值对 const key = content.slice(currentKeyStart, keyValueSeparatorIndex).trim(); const value = content.slice(keyValueSeparatorIndex + 1, i).trim(); result[key] = value.startsWith('{') ? parseNestedObject(value) : value; // 更新下一个键的起始位置 currentKeyStart = i + 1; keyValueSeparatorIndex = -1; } } } // 处理最后一个没有逗号结尾的键值对 if (keyValueSeparatorIndex !== -1) { const key = content.slice(currentKeyStart, keyValueSeparatorIndex).trim(); const value = content.slice(keyValueSeparatorIndex + 1).trim(); result[key] = value.startsWith('{') ? parseNestedObject(value) : value; } return result; } // 测试你的例子 const testString = '{dog : cat, joe: { jane: cat, peanut : dog }, fat : skinny}'; console.log(parseNestedObject(testString)); // 输出结果:{ dog: 'cat', joe: { jane: 'cat', peanut: 'dog' }, fat: 'skinny' }
这个版本完美解决了嵌套对象的解析问题,自动清理了空格,还加入了基本的输入校验,能处理你给出的测试用例,也能兼容更深层次的嵌套结构。
内容的提问来源于stack exchange,提问作者checkingJS
相关产品推荐
相关产品推荐

