39948-vm/frontend/src/lib/parseJson.ts
2026-03-24 15:40:35 +04:00

90 lines
2.5 KiB
TypeScript

/**
* JSON Parsing Utilities
*
* Shared utilities for safely parsing JSON values that may be strings or already parsed.
*/
/**
* Parses a value that might be a JSON string or already an object.
* Returns a typed object with fallback support.
*
* @param value - The value to parse (string, object, or undefined)
* @param fallback - Fallback value if parsing fails (defaults to empty object)
* @returns The parsed object or fallback
*
* @example
* const schema = parseJsonObject<ConstructorSchema>(page.ui_schema_json, {});
* const settings = parseJsonObject<Settings>(settingsValue, { enabled: false });
*/
export const parseJsonObject = <T>(value?: unknown, fallback?: T): T => {
if (!value) return (fallback || ({} as T)) as T;
try {
if (typeof value === 'string') {
const parsed = JSON.parse(value);
return (parsed || fallback || {}) as T;
}
if (typeof value === 'object') {
return value as T;
}
return (fallback || ({} as T)) as T;
} catch {
return (fallback || ({} as T)) as T;
}
};
/**
* Parses a JSON field that might be a string, object, or null.
* More lenient than parseJsonObject - returns the original value on parse error.
*
* @param value - The value to parse
* @returns The parsed value, original value, or null
*
* @example
* const content = parseJsonField(element.content_json);
* const style = parseJsonField(element.style_json);
*/
export const parseJsonField = (value: unknown): unknown => {
if (value === null || value === undefined) return null;
if (typeof value !== 'string') return value;
if (!value.trim()) return null;
try {
return JSON.parse(value);
} catch {
return value;
}
};
/**
* Extracts preview text from parsed content by checking common text field names.
*
* @param content - Parsed content object
* @returns The first text value found, or null
*
* @example
* const previewText = getElementPreviewText(parseJsonField(element.content_json));
*/
export const getElementPreviewText = (content: unknown): string | null => {
if (typeof content === 'string') return content;
if (!content || typeof content !== 'object') return null;
const candidateKeys = [
'title',
'text',
'subtitle',
'description',
'body',
'label',
'value',
];
const contentRecord = content as Record<string, unknown>;
const firstTextKey = candidateKeys.find(
(key) => typeof contentRecord[key] === 'string',
);
return firstTextKey ? String(contentRecord[firstTextKey]) : null;
};