← ToolBox
/ JSONPath 查询
🌙
🛣️ JSONPath 查询
使用 JSONPath 表达式(如 $.user.name, $.items[*].id, $..name)从 JSON 中查询数据。
查询
复制
清空
示例
查询结果(JSON)
等待查询...
已复制
const SAMPLE = JSON.stringify({store:{book:[{category:"ref",author:"Nigel Rees",title:"Sayings",price:8.95},{category:"fic",author:"Evelyn Waugh",title:"Sword",price:12.99}],bicycle:{color:"red",price:19.95}}}, null, 2); function evalPath(obj, expr){ if(!expr.startsWith('$')) throw new Error('JSONPath 必须以 $ 开头'); let paths = [obj]; const tokens = parseTokens(expr); for(const t of tokens){ const next = []; for(const cur of paths){ if(t.recursive){ collectAll(cur, t.key, next); } else if(t.all && Array.isArray(cur)){ cur.forEach(x => { if(t.key in x || t.key === null) next.push(t.key === null ? x : x[t.key]); }); } else if(t.all){ if(cur && typeof cur === 'object'){ for(const k in cur) next.push(cur[k]); } } else if(t.index !== null){ if(Array.isArray(cur) && cur[t.index] !== undefined) next.push(cur[t.index]); } else { if(cur && typeof cur === 'object' && t.key in cur) next.push(cur[t.key]); } } paths = next; } return paths; } function parseTokens(expr){ const tokens = []; let i = 1; while(i < expr.length){ if(expr[i] === '.'){ i++; if(expr[i] === '.'){ i++; let key = ''; while(i < expr.length && expr[i] !== '.' && expr[i] !== '[') key += expr[i++]; tokens.push({recursive:true, key:key, all:false, index:null}); } else { let key = ''; while(i < expr.length && expr[i] !== '.' && expr[i] !== '[') key += expr[i++]; if(key === '*') tokens.push({recursive:false, key:null, all:true, index:null}); else tokens.push({recursive:false, key:key, all:false, index:null}); } } else if(expr[i] === '['){ i++; if(expr[i] === '*'){ tokens.push({recursive:false, key:null, all:true, index:null}); i += 2; } else { let num = ''; while(i < expr.length && expr[i] !== ']') num += expr[i++]; i++; tokens.push({recursive:false, key:null, all:false, index:parseInt(num)}); } } else { i++; } } return tokens; } function collectAll(obj, key, out){ if(obj && typeof obj === 'object'){ if(key === '' || key === null){ for(const k in obj) out.push(obj[k]); } else if(key in obj){ out.push(obj[key]); } if(Array.isArray(obj)) obj.forEach(x => collectAll(x, key, out)); else for(const k in obj) collectAll(obj[k], key, out); } } function doQuery(){ setErr(''); try{ const data = JSON.parse(document.getElementById('input').value); const path = document.getElementById('path').value || '$'; const result = evalPath(data, path); setOut(JSON.stringify(result, null, 2)); setErr('✅ 匹配 ' + result.length + ' 项'); }catch(e){ setErr('❌ ' + e.message); } } function loadSample(){document.getElementById('input').value = SAMPLE; document.getElementById('path').value = '$..author'; doQuery();} function setOut(s){document.getElementById('output').textContent = s;} function setErr(s){const e = document.getElementById('err'); e.textContent = s || ''; e.className = 'err' + (s && s.startsWith('✅') ? ' ok' : '');} function clearAll(){document.getElementById('input').value = ''; document.getElementById('path').value = '$.'; setOut('等待查询...'); setErr('');} function getIndent(){const v=document.getElementById('indent').value;return v==='tab'?'\t':' '.repeat(parseInt(v));} function setOut(s){document.getElementById('output').textContent=s;} function setErr(s){const e=document.getElementById('err');e.textContent=s||'';e.className='err'+(s?'':' ok');} function clearAll(){document.getElementById('input').value='';setOut('等待输入...');setErr('');} function loadSample(){document.getElementById('input').value=SAMPLE;doBeautify();}