Files
ToolBox/src/utils/jsonFormatter/jsonPath.js
T
renjue 0044cd6e32
CI / docker (push) Failing after 1m55s
初始化 ToolBox 开发者工具箱。
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-25 10:32:25 +08:00

143 lines
3.8 KiB
JavaScript

export function parseJsonPath(jsonPath) {
if (!jsonPath || !jsonPath.trim()) return null
const path = jsonPath.trim()
// 移除开头的 $ 或 $.
const normalizedPath = path.replace(/^\$\.?/, '')
if (!normalizedPath) return []
// 解析路径段:支持 .key 和 [index] 或 [*]
const segments = []
let current = normalizedPath
let i = 0
while (i < current.length) {
if (current[i] === '[') {
// 数组索引
const endIndex = current.indexOf(']', i)
if (endIndex === -1) break
const indexStr = current.substring(i + 1, endIndex)
if (indexStr === '*') {
segments.push({ type: 'wildcard', index: '*' })
} else {
const index = parseInt(indexStr, 10)
if (!isNaN(index)) {
segments.push({ type: 'index', index })
}
}
i = endIndex + 1
} else if (current[i] === '.') {
i++
} else {
// 对象键
let keyEnd = i
while (keyEnd < current.length && current[keyEnd] !== '.' && current[keyEnd] !== '[') {
keyEnd++
}
const key = current.substring(i, keyEnd)
if (key) {
segments.push({ type: 'key', key })
}
i = keyEnd
}
}
return segments
}
export function pathToJsonPath(path) {
if (path === 'root') return '$'
return '$' + path.replace(/^root/, '')
}
export function pathMatchesJsonPath(path, jsonPathSegments) {
if (!jsonPathSegments || jsonPathSegments.length === 0) return true
// 将路径转换为段数组
const pathSegments = []
const pathStr = path === 'root' ? '' : path.replace(/^root\.?/, '')
if (!pathStr) {
return jsonPathSegments.length === 0
}
// 解析路径段
let current = pathStr
let i = 0
while (i < current.length) {
if (current[i] === '[') {
const endIndex = current.indexOf(']', i)
if (endIndex === -1) break
const indexStr = current.substring(i + 1, endIndex)
const index = parseInt(indexStr, 10)
if (!isNaN(index)) {
pathSegments.push({ type: 'index', index })
}
i = endIndex + 1
} else if (current[i] === '.') {
i++
} else {
let keyEnd = i
while (keyEnd < current.length && current[keyEnd] !== '.' && current[keyEnd] !== '[') {
keyEnd++
}
const key = current.substring(i, keyEnd)
if (key) {
pathSegments.push({ type: 'key', key })
}
i = keyEnd
}
}
// 精确匹配:路径段数必须等于 JSONPath 段数
if (pathSegments.length !== jsonPathSegments.length) return false
for (let i = 0; i < jsonPathSegments.length; i++) {
const jsonSeg = jsonPathSegments[i]
const pathSeg = pathSegments[i]
if (!pathSeg) return false
if (jsonSeg.type === 'wildcard') {
// 通配符匹配任何索引
if (pathSeg.type !== 'index') return false
} else if (jsonSeg.type === 'index') {
if (pathSeg.type !== 'index' || pathSeg.index !== jsonSeg.index) return false
} else if (jsonSeg.type === 'key') {
if (pathSeg.type !== 'key' || pathSeg.key !== jsonSeg.key) return false
}
}
return true
}
export function getDataByPath(obj, path) {
if (path === 'root') return obj
const pathStr = path.replace(/^root\.?/, '')
let current = obj
let i = 0
while (i < pathStr.length && current !== undefined && current !== null) {
if (pathStr[i] === '[') {
const endIdx = pathStr.indexOf(']', i)
const idx = parseInt(pathStr.substring(i + 1, endIdx), 10)
current = current[idx]
i = endIdx + 1
} else if (pathStr[i] === '.') {
i++
} else {
let keyEnd = i
while (keyEnd < pathStr.length && pathStr[keyEnd] !== '.' && pathStr[keyEnd] !== '[') {
keyEnd++
}
const key = pathStr.substring(i, keyEnd)
current = current[key]
i = keyEnd
}
}
return current
}