fix serialize and json tool to handle boolean type and number type field, and fix the nested rows in array and object type

This commit is contained in:
dwindown
2025-08-21 23:12:43 +07:00
parent 97459ea313
commit 22d333d932
6 changed files with 1926 additions and 3415 deletions

View File

@@ -6,6 +6,7 @@ const StructuredEditor = ({ onDataChange, initialData = {} }) => {
const [expandedNodes, setExpandedNodes] = useState(new Set(['root']));
const updateData = (newData) => {
console.log('📊 DATA UPDATE:', { keys: Object.keys(newData), totalProps: JSON.stringify(newData).length });
setData(newData);
onDataChange(newData);
};
@@ -21,11 +22,25 @@ const StructuredEditor = ({ onDataChange, initialData = {} }) => {
};
const addProperty = (obj, path) => {
const newObj = { ...obj };
const keys = Object.keys(newObj);
console.log('🔧 ADD PROPERTY - Before:', { path, dataKeys: Object.keys(data), objKeys: Object.keys(obj) });
const pathParts = path.split('.');
const newData = { ...data };
let current = newData;
// Navigate to the target object in the full data structure
for (let i = 1; i < pathParts.length; i++) {
current = current[pathParts[i]];
}
// Add new property to the target object
const keys = Object.keys(current);
const newKey = `property${keys.length + 1}`;
newObj[newKey] = '';
updateData(newObj);
current[newKey] = '';
console.log('🔧 ADD PROPERTY - After:', { path, newKey, dataKeys: Object.keys(newData), targetKeys: Object.keys(current) });
updateData(newData);
setExpandedNodes(new Set([...expandedNodes, path]));
};
@@ -69,6 +84,52 @@ const StructuredEditor = ({ onDataChange, initialData = {} }) => {
};
const updateValue = (value, path) => {
console.log('✏️ UPDATE VALUE:', { path, value, currentType: typeof getValue(path) });
const pathParts = path.split('.');
const newData = { ...data };
let current = newData;
for (let i = 1; i < pathParts.length - 1; i++) {
current = current[pathParts[i]];
}
const key = pathParts[pathParts.length - 1];
const currentValue = current[key];
const currentType = typeof currentValue;
// Preserve the current type when updating value
if (currentType === 'boolean') {
current[key] = value === 'true';
} else if (currentType === 'number') {
const numValue = Number(value);
current[key] = isNaN(numValue) ? 0 : numValue;
} else if (currentValue === null) {
current[key] = value === 'null' ? null : value;
} else {
// For strings and initial empty values, use auto-detection
if (currentValue === '' || currentValue === undefined) {
if (value === 'true' || value === 'false') {
current[key] = value === 'true';
} else if (value === 'null') {
current[key] = null;
} else if (!isNaN(value) && value !== '' && value.trim() !== '') {
current[key] = Number(value);
} else {
current[key] = value;
}
} else {
current[key] = value;
}
}
console.log('✏️ UPDATE VALUE - Result:', { path, newValue: current[key], newType: typeof current[key] });
updateData(newData);
};
const changeType = (newType, path) => {
console.log('🔄 CHANGE TYPE:', { path, newType, currentValue: getValue(path) });
const pathParts = path.split('.');
const newData = { ...data };
let current = newData;
@@ -80,45 +141,28 @@ const StructuredEditor = ({ onDataChange, initialData = {} }) => {
const key = pathParts[pathParts.length - 1];
const currentValue = current[key];
// Auto-detect type only when current value is empty/null/undefined
if (currentValue === '' || currentValue === null || currentValue === undefined) {
if (value === 'true' || value === 'false') {
current[key] = value === 'true';
} else if (value === 'null') {
current[key] = null;
} else if (!isNaN(value) && value !== '') {
current[key] = Number(value);
} else {
current[key] = value;
}
} else {
// If current value exists, preserve as string unless explicitly changed via type dropdown
current[key] = value;
}
updateData(newData);
};
const changeType = (newType, path) => {
const pathParts = path.split('.');
const newData = { ...data };
let current = newData;
for (let i = 1; i < pathParts.length - 1; i++) {
current = current[pathParts[i]];
}
const key = pathParts[pathParts.length - 1];
// Try to preserve value when changing types if possible
switch (newType) {
case 'string':
current[key] = '';
current[key] = currentValue === null ? '' : currentValue.toString();
break;
case 'number':
current[key] = 0;
if (typeof currentValue === 'string' && !isNaN(currentValue) && currentValue.trim() !== '') {
current[key] = Number(currentValue);
} else if (typeof currentValue === 'boolean') {
current[key] = currentValue ? 1 : 0;
} else {
current[key] = 0;
}
break;
case 'boolean':
current[key] = false;
if (typeof currentValue === 'string') {
current[key] = currentValue.toLowerCase() === 'true';
} else if (typeof currentValue === 'number') {
current[key] = currentValue !== 0;
} else {
current[key] = false;
}
break;
case 'array':
current[key] = [];
@@ -133,10 +177,20 @@ const StructuredEditor = ({ onDataChange, initialData = {} }) => {
current[key] = '';
}
console.log('🔄 CHANGE TYPE - Result:', { path, newValue: current[key], actualType: typeof current[key] });
updateData(newData);
setExpandedNodes(new Set([...expandedNodes, path]));
};
const getValue = (path) => {
const pathParts = path.split('.');
let current = data;
for (let i = 1; i < pathParts.length; i++) {
current = current[pathParts[i]];
}
return current;
};
const renameKey = (oldKey, newKey, path) => {
if (oldKey === newKey || !newKey.trim()) return;
@@ -241,17 +295,37 @@ const StructuredEditor = ({ onDataChange, initialData = {} }) => {
)}
{!canExpand ? (
<input
type="text"
value={
value === null ? 'null' :
value === undefined ? '' :
value.toString()
}
onChange={(e) => updateValue(e.target.value, path)}
className="flex-1 px-2 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 min-w-0"
placeholder="Value"
/>
typeof value === 'boolean' ? (
<div className="flex-1 flex items-center space-x-2">
<button
onClick={() => updateValue((!value).toString(), path)}
className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 ${
value ? 'bg-blue-600' : 'bg-gray-200 dark:bg-gray-600'
}`}
>
<span
className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
value ? 'translate-x-6' : 'translate-x-1'
}`}
/>
</button>
<span className="text-sm text-gray-600 dark:text-gray-400 font-mono">
{value.toString()}
</span>
</div>
) : (
<input
type="text"
value={
value === null ? 'null' :
value === undefined ? '' :
value.toString()
}
onChange={(e) => updateValue(e.target.value, path)}
className="flex-1 px-2 py-1 text-sm border border-gray-300 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 min-w-0"
placeholder="Value"
/>
)
) : (
<span className="flex-1 text-sm text-gray-600 dark:text-gray-400">
{Array.isArray(value) ? `Array (${value.length} items)` : `Object (${Object.keys(value).length} properties)`}