Skip to content

Commit fec4bf7

Browse files
committed
Add better documentation for JsonFile._validateNoUndefinedMembers(), based on PR feedback
1 parent 15489ab commit fec4bf7

File tree

1 file changed

+34
-14
lines changed

1 file changed

+34
-14
lines changed

libraries/node-core-library/src/JsonFile.ts

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -146,37 +146,57 @@ export class JsonFile {
146146
*/
147147
// tslint:disable-next-line:no-any
148148
public static validateNoUndefinedMembers(jsonObject: Object): void {
149-
return JsonFile._validateNoUndefinedMembers(jsonObject, '');
149+
return JsonFile._validateNoUndefinedMembers(jsonObject, []);
150150
}
151151

152152
// Private implementation of validateNoUndefinedMembers()
153-
private static _validateNoUndefinedMembers(jsonObject: Object, path: string): void {
153+
private static _validateNoUndefinedMembers(jsonObject: Object, keyPath: string[]): void {
154154
if (!jsonObject) {
155155
return;
156156
}
157157
if (typeof jsonObject === 'object') {
158158
for (const key of Object.keys(jsonObject)) {
159-
let fullPath: string = path;
160-
if (Array.isArray(jsonObject)) {
161-
fullPath += `[${key}]`;
162-
} else if (/^[a-z_0-9]+$/i.test(key)) {
163-
if (fullPath) {
164-
fullPath += '.';
165-
}
166-
fullPath += `${key}`;
167-
} else {
168-
fullPath += `["${key.replace(/["]/g, '\\"')}"]`;
169-
}
159+
keyPath.push(key);
170160

171161
// tslint:disable-next-line:no-any
172162
const value: any = jsonObject[key];
173163
if (value === undefined) {
164+
const fullPath: string = JsonFile._formatKeyPath(keyPath);
174165
throw new Error(`The value for ${fullPath} is undefined`);
175166
}
176167

177-
JsonFile._validateNoUndefinedMembers(value, fullPath);
168+
JsonFile._validateNoUndefinedMembers(value, keyPath);
169+
keyPath.pop();
170+
}
171+
}
172+
}
173+
174+
// Given this input: ['items', '4', 'syntax', 'parameters', 'string "with" symbols", 'type']
175+
// Return this string: items[4].syntax.parameters["string \"with\" symbols"].type
176+
private static _formatKeyPath(keyPath: string[]): string {
177+
let result: string = '';
178+
179+
for (const key of keyPath) {
180+
if (/^[0-9]+$/.test(key)) {
181+
// It's an integer, so display like this: parent[123]
182+
result += `[${key}]`;
183+
} else if (/^[a-z_][a-z_0-9]*$/i.test(key)) {
184+
// It's an alphanumeric identifier, so display like this: parent.name
185+
if (result) {
186+
result += '.';
187+
}
188+
result += `${key}`;
189+
} else {
190+
// It's a freeform string, so display like this: parent["A path: \"C:\\file\""]
191+
192+
// Convert this: A path: "C:\file"
193+
// To this: A path: \"C:\\file\"
194+
const escapedKey: string = key.replace(/[\\]/g, '\\\\') // escape backslashes
195+
.replace(/["]/g, '\\'); // escape quotes
196+
result += `["${escapedKey}"]`;
178197
}
179198
}
199+
return result;
180200
}
181201

182202
/**

0 commit comments

Comments
 (0)