143 lines
3.8 KiB
JavaScript
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
|
|
}
|