lib/util/jsonUtils.ts (43 lines of code) (raw):
import { FilePosition, getInfo } from "@azure-tools/openapi-tools-common";
import { default as jsonPointer } from "json-pointer";
import { JSONPath } from "jsonpath-plus";
export const jsonPathToArray = (jsonPath: string): string[] => {
return (JSONPath as any).toPathArray(jsonPath);
};
export const jsonPathToPointer = (jsonPath: string): string => {
return jsonPointer.compile(jsonPathToArray(jsonPath).slice(1));
};
export const getFilePositionFromJsonPath = (
obj: any,
jsonPath: string
): FilePosition | undefined => {
if (!jsonPath) {
return undefined;
}
const pathArr = jsonPathToArray(jsonPath.substr(1));
/*
* when jsonPath='/providers/Microsoft.Provider/resource',
* the split pathArr will be ['/providers/Microsoft','Provider/resource'].
* Only in this case, these two elements in the array need to be composed together by '.'.
* So restrict the condition to the path element ends with /providers/Microsoft.
*/
const newPathArr = pathArr.slice(0);
const index = newPathArr.findIndex((str) => str.includes("/providers/Microsoft"));
if (
index !== -1 &&
newPathArr[index + 1] !== undefined &&
newPathArr[index].slice(-20) === "/providers/Microsoft"
) {
newPathArr[index] += "." + newPathArr[index + 1];
newPathArr.splice(index + 1, 1);
}
try {
const target = jsonPointer.get(obj, jsonPointer.compile(newPathArr));
const info = getInfo(target);
if (info !== undefined) {
return info.position;
}
} catch (e) {
// Pass
}
const lastProperty = newPathArr.pop();
const target = jsonPointer.get(obj, jsonPointer.compile(newPathArr));
const info = getInfo(target);
if (info !== undefined && lastProperty !== undefined) {
return info.primitiveProperties[lastProperty];
}
return undefined;
};