90 lines
3.4 KiB
JavaScript
90 lines
3.4 KiB
JavaScript
|
|
/**
|
||
|
|
* Utility functions for tracking and managing field names in JSON documents
|
||
|
|
*/
|
||
|
|
/**
|
||
|
|
* Extracts field names from a JSON document
|
||
|
|
* @param jsonObject The JSON object to extract field names from
|
||
|
|
* @param options Configuration options
|
||
|
|
* @returns An array of field paths (e.g., "user.name", "addresses[0].city")
|
||
|
|
*/
|
||
|
|
export function extractFieldNamesFromJson(jsonObject, options = {}) {
|
||
|
|
const { maxDepth = 5, currentDepth = 0, currentPath = '', fieldNames = new Set() } = options;
|
||
|
|
if (jsonObject === null ||
|
||
|
|
jsonObject === undefined ||
|
||
|
|
typeof jsonObject !== 'object' ||
|
||
|
|
currentDepth >= maxDepth) {
|
||
|
|
return Array.from(fieldNames);
|
||
|
|
}
|
||
|
|
if (Array.isArray(jsonObject)) {
|
||
|
|
// For arrays, we'll just check the first item to avoid explosion of paths
|
||
|
|
if (jsonObject.length > 0) {
|
||
|
|
const arrayPath = currentPath ? `${currentPath}[0]` : '[0]';
|
||
|
|
extractFieldNamesFromJson(jsonObject[0], {
|
||
|
|
maxDepth,
|
||
|
|
currentDepth: currentDepth + 1,
|
||
|
|
currentPath: arrayPath,
|
||
|
|
fieldNames
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else {
|
||
|
|
// For objects, process each property
|
||
|
|
for (const key of Object.keys(jsonObject)) {
|
||
|
|
const value = jsonObject[key];
|
||
|
|
const fieldPath = currentPath ? `${currentPath}.${key}` : key;
|
||
|
|
// Add this field path
|
||
|
|
fieldNames.add(fieldPath);
|
||
|
|
// Recursively process nested objects
|
||
|
|
if (typeof value === 'object' && value !== null) {
|
||
|
|
extractFieldNamesFromJson(value, {
|
||
|
|
maxDepth,
|
||
|
|
currentDepth: currentDepth + 1,
|
||
|
|
currentPath: fieldPath,
|
||
|
|
fieldNames
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return Array.from(fieldNames);
|
||
|
|
}
|
||
|
|
/**
|
||
|
|
* Maps field names to standard field names based on common patterns
|
||
|
|
* @param fieldName The field name to map
|
||
|
|
* @returns The standard field name if a match is found, or null if no match
|
||
|
|
*/
|
||
|
|
export function mapToStandardField(fieldName) {
|
||
|
|
// Standard field mappings
|
||
|
|
const standardMappings = {
|
||
|
|
'title': ['title', 'name', 'headline', 'subject'],
|
||
|
|
'description': ['description', 'summary', 'content', 'text', 'body'],
|
||
|
|
'author': ['author', 'creator', 'user', 'owner', 'by'],
|
||
|
|
'date': ['date', 'created', 'createdAt', 'timestamp', 'published'],
|
||
|
|
'url': ['url', 'link', 'href', 'source'],
|
||
|
|
'image': ['image', 'thumbnail', 'photo', 'picture'],
|
||
|
|
'tags': ['tags', 'categories', 'keywords', 'topics']
|
||
|
|
};
|
||
|
|
// Check for matches
|
||
|
|
for (const [standardField, possibleMatches] of Object.entries(standardMappings)) {
|
||
|
|
// Exact match
|
||
|
|
if (possibleMatches.includes(fieldName)) {
|
||
|
|
return standardField;
|
||
|
|
}
|
||
|
|
// Path match (e.g., "user.name" matches "name")
|
||
|
|
const parts = fieldName.split('.');
|
||
|
|
const lastPart = parts[parts.length - 1];
|
||
|
|
if (possibleMatches.includes(lastPart)) {
|
||
|
|
return standardField;
|
||
|
|
}
|
||
|
|
// Array match (e.g., "items[0].name" matches "name")
|
||
|
|
if (fieldName.includes('[')) {
|
||
|
|
for (const part of parts) {
|
||
|
|
const cleanPart = part.split('[')[0];
|
||
|
|
if (possibleMatches.includes(cleanPart)) {
|
||
|
|
return standardField;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
//# sourceMappingURL=fieldNameTracking.js.map
|