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:
@@ -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)`}
|
||||
|
||||
Reference in New Issue
Block a user