diff --git a/packages/tools/src/stringTools.ts b/packages/tools/src/stringTools.ts index 80f7d8585..47aecea40 100644 --- a/packages/tools/src/stringTools.ts +++ b/packages/tools/src/stringTools.ts @@ -44,3 +44,18 @@ export function stringifyCellValue(value) { if (_isPlainObject(value) || _isArray(value)) return JSON.stringify(value); return value; } + +export function safeJsonParse(json, defaultValue?, logError = false) { + try { + return JSON.parse(json); + } catch (err) { + if (logError) { + console.error(`Error parsing JSON value "${json}"`, err); + } + return defaultValue; + } +} + +export function isJsonLikeLongString(value) { + return _isString(value) && value.length > 100 && value.match(/^\s*\{.*\}\s*$|^\s*\[.*\]\s*$/); +} diff --git a/packages/web/src/datagrid/DataGridCell.svelte b/packages/web/src/datagrid/DataGridCell.svelte index 34cf70879..8b08391e4 100644 --- a/packages/web/src/datagrid/DataGridCell.svelte +++ b/packages/web/src/datagrid/DataGridCell.svelte @@ -37,7 +37,7 @@ import _ from 'lodash'; import ShowFormButton from '../formview/ShowFormButton.svelte'; import { getBoolSettingsValue } from '../settings/settingsTools'; - import { arrayToHexString } from 'dbgate-tools'; + import { arrayToHexString, isJsonLikeLongString, safeJsonParse } from 'dbgate-tools'; import { showModal } from '../modals/modalTools'; import DictionaryLookupModal from '../modals/DictionaryLookupModal.svelte'; import { openJsonDocument } from '../tabs/JsonTab.svelte'; @@ -84,6 +84,7 @@ $: style = computeStyle(maxWidth, col); $: isJson = _.isPlainObject(value) && !(value?.type == 'Buffer' && _.isArray(value.data)) && !value.$oid; + $: jsonParsedValue = isJsonLikeLongString(value) ? safeJsonParse(value) : null; false {:else if _.isNumber(value)} {formatNumber(value)} - {:else if _.isString(value)} + {:else if _.isString(value) && !jsonParsedValue} {#if dateTimeRegex.test(value)} {formatDateTime(value)} @@ -134,6 +135,10 @@ (JSON) {:else if _.isArray(value)} [{value.length} items] + {:else if _.isPlainObject(jsonParsedValue)} + (JSON) + {:else if _.isArray(jsonParsedValue)} + [{jsonParsedValue.length} items] {:else} {value.toString()} {/if} @@ -156,7 +161,11 @@ openJsonDocument(value, undefined, true)} /> {/if} - {#if _.isArray(value)} + {#if jsonParsedValue && _.isPlainObject(jsonParsedValue)} + openJsonDocument(jsonParsedValue, undefined, true)} /> + {/if} + + {#if _.isArray(jsonParsedValue || value)} @@ -169,7 +178,7 @@ }, { editor: { - rows: value, + rows: jsonParsedValue || value, structure: { __isDynamicStructure: true, columns: [] }, }, } diff --git a/packages/web/src/datagrid/gridutil.ts b/packages/web/src/datagrid/gridutil.ts index 9bffcfc5b..b0d15275f 100644 --- a/packages/web/src/datagrid/gridutil.ts +++ b/packages/web/src/datagrid/gridutil.ts @@ -3,6 +3,7 @@ import { SeriesSizes } from './SeriesSizes'; import { CellAddress } from './selection'; import { GridDisplay } from 'dbgate-datalib'; import Grider from './Grider'; +import { isJsonLikeLongString, safeJsonParse } from 'dbgate-tools'; export function countColumnSizes(grider: Grider, columns, containerWidth, display: GridDisplay) { const columnSizes = new SeriesSizes(); @@ -68,6 +69,7 @@ export function countColumnSizes(grider: Grider, columns, containerWidth, displa let text = value; if (_.isArray(value)) text = `[${value.length} items]`; else if (value?.$oid) text = `ObjectId("${value.$oid}")`; + else if (isJsonLikeLongString(value) && safeJsonParse(value)) text = '(JSON)'; const width = context.measureText(text).width + 8; // console.log('colName', colName, text, width); columnSizes.putSizeOverride(colIndex, width); diff --git a/packages/web/src/stores.ts b/packages/web/src/stores.ts index 7f6885ad7..67c2f560b 100644 --- a/packages/web/src/stores.ts +++ b/packages/web/src/stores.ts @@ -2,9 +2,9 @@ import { writable, derived, readable } from 'svelte/store'; import { ExtensionsDirectory } from 'dbgate-types'; import invalidateCommands from './commands/invalidateCommands'; import getElectron from './utility/getElectron'; -import { GlobalCommand } from './commands/registerCommand'; import { useConfig, useSettings } from './utility/metadataLoaders'; import _ from 'lodash'; +import { safeJsonParse } from 'dbgate-tools'; export interface TabDefinition { title: string; @@ -18,18 +18,9 @@ export interface TabDefinition { tabOrder?: number; } -function safeJsonParse(json, defaultValue) { - try { - return JSON.parse(json); - } catch (err) { - console.error(`Error parsing JSON value "${json}"`, err); - return defaultValue; - } -} - export function writableWithStorage(defaultValue: T, storageName) { const init = localStorage.getItem(storageName); - const res = writable(init ? safeJsonParse(init, defaultValue) : defaultValue); + const res = writable(init ? safeJsonParse(init, defaultValue, true) : defaultValue); res.subscribe(value => { localStorage.setItem(storageName, JSON.stringify(value)); });