diff --git a/Build/Sources/TypeScript/backend/form-engine/element/json-element.ts b/Build/Sources/TypeScript/backend/form-engine/element/json-element.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0a3b678e48e18ec2151f2d613bea6fb540eecdd4
--- /dev/null
+++ b/Build/Sources/TypeScript/backend/form-engine/element/json-element.ts
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+import {Resizable} from './modifier/resizable';
+import {Tabbable} from './modifier/tabbable';
+
+/**
+ * Module: @typo3/backend/form-engine/element/json-element
+ *
+ * Functionality for the json element
+ *
+ * @example
+ * <typo3-formengine-element-json recordFieldId="some-id">
+ *   ...
+ * </typo3-formengine-element-json>
+ *
+ * This is based on W3C custom elements ("web components") specification, see
+ * https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements
+ */
+class JsonElement extends HTMLElement {
+  private element: HTMLTextAreaElement = null;
+
+  public connectedCallback(): void {
+    this.element = document.getElementById((this.getAttribute('recordFieldId') || '' as string)) as HTMLTextAreaElement;
+
+    if (!this.element) {
+      return;
+    }
+
+    Resizable.enable(this.element);
+    Tabbable.enable(this.element);
+  }
+}
+
+window.customElements.define('typo3-formengine-element-json', JsonElement);
diff --git a/Build/Sources/TypeScript/t3editor/element/code-mirror-element.ts b/Build/Sources/TypeScript/t3editor/element/code-mirror-element.ts
index b3aa02fd33263511fd2f3bf41ae7e153b3565e4f..f5a64d6d0eb287ffca264c127cd207547e3e075c 100644
--- a/Build/Sources/TypeScript/t3editor/element/code-mirror-element.ts
+++ b/Build/Sources/TypeScript/t3editor/element/code-mirror-element.ts
@@ -13,7 +13,16 @@
 
 import {LitElement, html, css} from 'lit';
 import {customElement, property, state} from 'lit/decorators';
-import {EditorView, ViewUpdate, lineNumbers, highlightSpecialChars, drawSelection, keymap, KeyBinding} from '@codemirror/view';
+import {
+  EditorView,
+  ViewUpdate,
+  lineNumbers,
+  highlightSpecialChars,
+  drawSelection,
+  keymap,
+  KeyBinding,
+  placeholder
+} from '@codemirror/view';
 import {Extension, EditorState} from '@codemirror/state';
 import {syntaxHighlighting, defaultHighlightStyle} from '@codemirror/language';
 import {defaultKeymap,  indentWithTab} from '@codemirror/commands';
@@ -47,6 +56,7 @@ export class CodeMirrorElement extends LitElement {
   @property({type: Boolean, reflect: true}) fullscreen: boolean = false;
 
   @property({type: String}) label: string;
+  @property({type: String}) placeholder: string;
   @property({type: String}) panel: string = 'bottom';
 
   @state() editorView: EditorView = null;
@@ -185,6 +195,10 @@ export class CodeMirrorElement extends LitElement {
       extensions.push(EditorState.readOnly.of(true));
     }
 
+    if (this.placeholder) {
+      extensions.push(placeholder(this.placeholder));
+    }
+
     if (this.mode) {
       const modeImplementation = <Extension[]>await executeJavaScriptModuleInstruction(this.mode);
       extensions.push(...modeImplementation);
diff --git a/typo3/sysext/backend/Classes/Form/Element/JsonElement.php b/typo3/sysext/backend/Classes/Form/Element/JsonElement.php
new file mode 100644
index 0000000000000000000000000000000000000000..5551ad417023edfd251f563072fcea744e8393c6
--- /dev/null
+++ b/typo3/sysext/backend/Classes/Form/Element/JsonElement.php
@@ -0,0 +1,247 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Backend\Form\Element;
+
+use TYPO3\CMS\Core\Page\JavaScriptModuleInstruction;
+use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Core\Utility\MathUtility;
+use TYPO3\CMS\Core\Utility\StringUtility;
+use TYPO3\CMS\T3editor\Registry\AddonRegistry;
+use TYPO3\CMS\T3editor\Registry\ModeRegistry;
+use TYPO3\CMS\T3editor\T3editor;
+
+/**
+ * Handles type=json elements.
+ *
+ * Renders either a code editor or a standard textarea.
+ */
+class JsonElement extends AbstractFormElement
+{
+    /**
+     * Default field information enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldInformation = [
+        'tcaDescription' => [
+            'renderType' => 'tcaDescription',
+        ],
+    ];
+
+    /**
+     * Default field wizards enabled for this element.
+     *
+     * @var array
+     */
+    protected $defaultFieldWizard = [
+        'localizationStateSelector' => [
+            'renderType' => 'localizationStateSelector',
+        ],
+        'otherLanguageContent' => [
+            'renderType' => 'otherLanguageContent',
+            'after' => [
+                'localizationStateSelector',
+            ],
+        ],
+        'defaultLanguageDifferences' => [
+            'renderType' => 'defaultLanguageDifferences',
+            'after' => [
+                'otherLanguageContent',
+            ],
+        ],
+    ];
+
+    public function render(): array
+    {
+        $resultArray = $this->initializeResultArray();
+
+        $parameterArray = $this->data['parameterArray'];
+        $config = $parameterArray['fieldConf']['config'];
+        $readOnly = (bool)($config['readOnly'] ?? false);
+        $placeholder = trim((string)($config['placeholder'] ?? ''));
+        $enableCodeEditor = ($config['enableCodeEditor'] ?? true) && ExtensionManagementUtility::isLoaded('t3editor');
+
+        $itemValue = '';
+        if (!empty($parameterArray['itemFormElValue'])) {
+            try {
+                $itemValue = (string)json_encode($parameterArray['itemFormElValue'], JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_THROW_ON_ERROR);
+            } catch (\JsonException) {
+            }
+        }
+
+        $width = null;
+        if ($config['cols'] ?? false) {
+            $width = $this->formMaxWidth(MathUtility::forceIntegerInRange($config['cols'], $this->minimumInputWidth, $this->maxInputWidth));
+        }
+
+        $rows = MathUtility::forceIntegerInRange(($config['rows'] ?? 5) ?: 5, 1, 20);
+        $originalRows = $rows;
+        if (($itemFormElementValueLength = strlen($itemValue)) > 80) {
+            $calculatedRows = MathUtility::forceIntegerInRange(
+                (int)round($itemFormElementValueLength / 40),
+                count(explode(LF, $itemValue)),
+                20
+            );
+            if ($originalRows < $calculatedRows) {
+                $rows = $calculatedRows;
+            }
+        }
+
+        $fieldInformationResult = $this->renderFieldInformation();
+        $fieldInformationHtml = $fieldInformationResult['html'];
+        $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);
+
+        // Early return readonly display in case t3editor is not available
+        if ($readOnly && !$enableCodeEditor) {
+            $html = [];
+            $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
+            $html[] =   $fieldInformationHtml;
+            $html[] =   '<div class="form-wizards-wrap">';
+            $html[] =       '<div class="form-wizards-element">';
+            $html[] =           '<div class="form-control-wrap"' . ($width ? ' style="max-width: ' . $width . 'px">' : '>');
+            $html[] =               '<textarea class="form-control text-monospace" rows="' . $rows . '" disabled>';
+            $html[] =                   htmlspecialchars($itemValue);
+            $html[] =               '</textarea>';
+            $html[] =           '</div>';
+            $html[] =       '</div>';
+            $html[] =   '</div>';
+            $html[] = '</div>';
+            $resultArray['html'] = implode(LF, $html);
+            return $resultArray;
+        }
+
+        $fieldId = StringUtility::getUniqueId('formengine-json-');
+        $itemName = (string)$parameterArray['itemFormElName'];
+        $attributes = [
+            'id' => $fieldId,
+            'name' => $itemName,
+            'wrap' => 'off',
+            'rows' => (string)$rows,
+            'class' => 'form-control text-monospace',
+            'data-formengine-validation-rules' => $this->getValidationDataAsJsonString($config),
+        ];
+
+        if ($readOnly) {
+            $attributes['disabled'] = '';
+        }
+
+        if ($placeholder !== '') {
+            $attributes['placeholder'] = $placeholder;
+        }
+
+        // Use CodeMirror if available
+        if ($enableCodeEditor) {
+            // Compile and register t3editor configuration
+            GeneralUtility::makeInstance(T3editor::class)->registerConfiguration();
+
+            $modeRegistry = GeneralUtility::makeInstance(ModeRegistry::class);
+            $mode = $modeRegistry->isRegistered('json')
+                ? $modeRegistry->getByFormatCode('json')
+                : $modeRegistry->getDefaultMode();
+
+            $addons = $keymaps = [];
+            foreach (GeneralUtility::makeInstance(AddonRegistry::class)->getAddons() as $addon) {
+                foreach ($addon->getCssFiles() as $cssFile) {
+                    $resultArray['stylesheetFiles'][] = $cssFile;
+                }
+                if (($module = $addon->getModule())) {
+                    $addons[] = $module;
+                }
+                if (($keymap = $addon->getKeymap())) {
+                    $keymaps[] = $keymap;
+                }
+            }
+
+            $codeMirrorConfig = [
+                'label' => $this->data['tableName'] . ' > ' . $this->data['fieldName'],
+                'mode' => GeneralUtility::jsonEncodeForHtmlAttribute($mode->getModule(), false),
+            ];
+
+            if ($readOnly) {
+                $codeMirrorConfig['readonly'] = '';
+            }
+            if ($placeholder !== '') {
+                $codeMirrorConfig['placeholder'] = $placeholder;
+            }
+            if ($addons !== []) {
+                $codeMirrorConfig['addons'] = GeneralUtility::jsonEncodeForHtmlAttribute($addons, false);
+            }
+            if ($keymaps !== []) {
+                $codeMirrorConfig['keymaps'] = GeneralUtility::jsonEncodeForHtmlAttribute($keymaps, false);
+            }
+
+            $resultArray['javaScriptModules'][] = JavaScriptModuleInstruction::create('@typo3/t3editor/element/code-mirror-element.js');
+            $editorHtml = '
+                <typo3-t3editor-codemirror ' . GeneralUtility::implodeAttributes($codeMirrorConfig, true, true) . '>
+                    <textarea ' . GeneralUtility::implodeAttributes($attributes, true, true) . '>' . htmlspecialchars($itemValue) . '</textarea>
+                    <input type="hidden" name="target" value="0" />
+                    <input type="hidden" name="effectivePid" value="' . htmlspecialchars((string)($this->data['effectivePid'] ?? '0')) . '" />
+                </typo3-t3editor-codemirror>';
+        } else {
+            $attributes['class'] = implode(' ', array_merge(explode(' ', $attributes['class']), ['formengine-textarea', 't3js-enable-tab']));
+            $resultArray['javaScriptModules'][] = JavaScriptModuleInstruction::create('@typo3/backend/form-engine/element/json-element.js');
+            $editorHtml = '
+                <typo3-formengine-element-json recordFieldId="' . htmlspecialchars($fieldId) . '">
+                    <textarea ' . GeneralUtility::implodeAttributes($attributes, true, true) . '>' . htmlspecialchars($itemValue) . '</textarea>
+                </typo3-formengine-element-json>';
+        }
+
+        $additionalHtml = [];
+        if (!$readOnly) {
+            $fieldControlResult = $this->renderFieldControl();
+            $fieldControlHtml = $fieldControlResult['html'];
+            $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldControlResult, false);
+
+            if (!empty($fieldControlHtml)) {
+                $additionalHtml[] = '<div class="form-wizards-items-aside form-wizards-items-aside--field-control">';
+                $additionalHtml[] =     '<div class="btn-group">';
+                $additionalHtml[] =         $fieldControlHtml;
+                $additionalHtml[] =     '</div>';
+                $additionalHtml[] = '</div>';
+            }
+
+            $fieldWizardResult = $this->renderFieldWizard();
+            $fieldWizardHtml = $fieldWizardResult['html'];
+            $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false);
+
+            if (!empty($fieldWizardHtml)) {
+                $additionalHtml[] = '<div class="form-wizards-items-bottom">';
+                $additionalHtml[] =     $fieldWizardHtml;
+                $additionalHtml[] = '</div>';
+            }
+        }
+
+        $html = [];
+        $html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
+        $html[] =   $fieldInformationHtml;
+        $html[] =   '<div class="form-control-wrap"' . ($width ? ' style="max-width: ' . $width . 'px">' : '>');
+        $html[] =       '<div class="form-wizards-wrap">';
+        $html[] =           '<div class="form-wizards-element">';
+        $html[] =               $editorHtml;
+        $html[] =           '</div>';
+        $html[] =           implode(LF, $additionalHtml);
+        $html[] =       '</div>';
+        $html[] =   '</div>';
+        $html[] = '</div>';
+
+        $resultArray['html'] = implode(LF, $html);
+
+        return $resultArray;
+    }
+}
diff --git a/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaColumnsProcessPlaceholders.php b/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaColumnsProcessPlaceholders.php
index d050dbfe61b8ce8690469ac41ce0985652b81014..fb98cfda35cc78c0929146e37821b242ddb75b71 100644
--- a/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaColumnsProcessPlaceholders.php
+++ b/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaColumnsProcessPlaceholders.php
@@ -44,6 +44,7 @@ class TcaColumnsProcessPlaceholders implements FormDataProviderInterface
                     && $fieldConfig['config']['type'] !== 'password'
                     && $fieldConfig['config']['type'] !== 'datetime'
                     && $fieldConfig['config']['type'] !== 'color'
+                    && $fieldConfig['config']['type'] !== 'json'
                 )
             ) {
                 continue;
diff --git a/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaInputPlaceholders.php b/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaInputPlaceholders.php
index c6d64e9fd6e02cc710bee887e8bdc842ae795222..8075737399f01955e10945558a6fe065648f793b 100644
--- a/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaInputPlaceholders.php
+++ b/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaInputPlaceholders.php
@@ -51,6 +51,7 @@ class TcaInputPlaceholders implements FormDataProviderInterface
                     && $fieldConfig['config']['type'] !== 'password'
                     && $fieldConfig['config']['type'] !== 'datetime'
                     && $fieldConfig['config']['type'] !== 'color'
+                    && $fieldConfig['config']['type'] !== 'json'
                 )
             ) {
                 continue;
diff --git a/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaJson.php b/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaJson.php
new file mode 100644
index 0000000000000000000000000000000000000000..a222480ddf8212d3124abc95ff635c4b776cb11d
--- /dev/null
+++ b/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaJson.php
@@ -0,0 +1,51 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Backend\Form\FormDataProvider;
+
+use TYPO3\CMS\Backend\Form\FormDataProviderInterface;
+
+/**
+ * Resolve and prepare json data.
+ */
+class TcaJson extends AbstractDatabaseRecordProvider implements FormDataProviderInterface
+{
+    public function addData(array $result): array
+    {
+        // Currently only new records are considered
+        if ($result['command'] !== 'new') {
+            return $result;
+        }
+
+        foreach ($result['processedTca']['columns'] as $fieldName => $fieldConfig) {
+            if (($fieldConfig['config']['type'] ?? '') !== 'json') {
+                continue;
+            }
+
+            // Ensure that even for new records, the field is always an array - especially if a default value is defined
+            if (is_string($result['databaseRow'][$fieldName])) {
+                try {
+                    $result['databaseRow'][$fieldName] = json_decode($result['databaseRow'][$fieldName], true, 512, JSON_THROW_ON_ERROR);
+                } catch (\JsonException) {
+                    $result['databaseRow'][$fieldName] = [];
+                }
+            }
+        }
+
+        return $result;
+    }
+}
diff --git a/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaRecordTitle.php b/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaRecordTitle.php
index 86ce0a6f0ea4bb1253c4fe24658d39f103b3fd93..273964dff8960f7b7c31c4b7ed86984fbdc2fb12 100644
--- a/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaRecordTitle.php
+++ b/typo3/sysext/backend/Classes/Form/FormDataProvider/TcaRecordTitle.php
@@ -193,6 +193,9 @@ class TcaRecordTitle implements FormDataProviderInterface
                 break;
             case 'flex':
                 // @todo: Check if and how a label could be generated from flex field data
+                break;
+            case 'json':
+                // @todo: Check if and how a label could be generated from json field data
             default:
         }
 
diff --git a/typo3/sysext/backend/Classes/Form/NodeFactory.php b/typo3/sysext/backend/Classes/Form/NodeFactory.php
index e0f88fb7e80124b994dbb743b88e84eab69c897a..069f8f5949a16827be27859ca88cf8fb7ce4373b 100644
--- a/typo3/sysext/backend/Classes/Form/NodeFactory.php
+++ b/typo3/sysext/backend/Classes/Form/NodeFactory.php
@@ -107,6 +107,7 @@ class NodeFactory
         'category' => Element\CategoryElement::class,
         'passthrough' => Element\PassThroughElement::class,
         'belayoutwizard' => Element\BackendLayoutWizardElement::class,
+        'json' => Element\JsonElement::class,
 
         // Default classes to enrich single elements
         'fieldControl' => NodeExpansion\FieldControl::class,
diff --git a/typo3/sysext/backend/Classes/Form/Utility/FormEngineUtility.php b/typo3/sysext/backend/Classes/Form/Utility/FormEngineUtility.php
index c18586f89c6233070226cf9c02a654d8626842a9..fc8b3715fd194517faa5134fc5e7e7695a44aab4 100644
--- a/typo3/sysext/backend/Classes/Form/Utility/FormEngineUtility.php
+++ b/typo3/sysext/backend/Classes/Form/Utility/FormEngineUtility.php
@@ -52,6 +52,7 @@ class FormEngineUtility
         'datetime' => ['size', 'readOnly'],
         'color' => ['size', 'readOnly'],
         'text' => ['cols', 'rows', 'wrap', 'max', 'readOnly'],
+        'json' => ['cols', 'rows', 'readOnly'],
         'check' => ['cols', 'readOnly'],
         'select' => ['size', 'autoSizeMax', 'maxitems', 'minitems', 'readOnly', 'treeConfig', 'fileFolderConfig'],
         'category' => ['size', 'maxitems', 'minitems', 'readOnly', 'treeConfig'],
diff --git a/typo3/sysext/backend/Classes/RecordList/DatabaseRecordList.php b/typo3/sysext/backend/Classes/RecordList/DatabaseRecordList.php
index 4f496e2dfe3f617133c5765d133166685e5c8444..245a4be3bbc720b563655f402c18ed6f8540ec23 100644
--- a/typo3/sysext/backend/Classes/RecordList/DatabaseRecordList.php
+++ b/typo3/sysext/backend/Classes/RecordList/DatabaseRecordList.php
@@ -2391,6 +2391,7 @@ class DatabaseRecordList
                     }
                 } elseif ($fieldType === 'input'
                     || $fieldType === 'text'
+                    || $fieldType === 'json'
                     || $fieldType === 'flex'
                     || $fieldType === 'email'
                     || $fieldType === 'link'
@@ -2435,6 +2436,7 @@ class DatabaseRecordList
                 }
                 if ($fieldType === 'input'
                     || $fieldType === 'text'
+                    || $fieldType === 'json'
                     || $fieldType === 'flex'
                     || $fieldType === 'email'
                     || $fieldType === 'link'
diff --git a/typo3/sysext/backend/Classes/Search/LiveSearch/DatabaseRecordProvider.php b/typo3/sysext/backend/Classes/Search/LiveSearch/DatabaseRecordProvider.php
index 545d12539736119034397e935896a4e62ff58dde..0b25202935e5f179443fd862a585ae94159c7b75 100644
--- a/typo3/sysext/backend/Classes/Search/LiveSearch/DatabaseRecordProvider.php
+++ b/typo3/sysext/backend/Classes/Search/LiveSearch/DatabaseRecordProvider.php
@@ -340,6 +340,7 @@ final class DatabaseRecordProvider implements SearchProviderInterface
         $searchableFieldTypes = [
             'input',
             'text',
+            'json',
             'flex',
             'email',
             'link',
diff --git a/typo3/sysext/backend/Classes/Utility/BackendUtility.php b/typo3/sysext/backend/Classes/Utility/BackendUtility.php
index 30435683019ad15c46aca0e8bd95ae6ae56505c4..841a6bfe7550cf6256953fee92cb057b6ce023d3 100644
--- a/typo3/sysext/backend/Classes/Utility/BackendUtility.php
+++ b/typo3/sysext/backend/Classes/Utility/BackendUtility.php
@@ -1544,17 +1544,6 @@ class BackendUtility
             GeneralUtility::callUserFunction($_funcRef, $theColConf, $referenceObject);
         }
 
-        // For database type "JSON" the value in decoded state is most likely an array. This is not compatible with
-        // the "human-readable" processing and returning promise of this method. Thus, we ensure to handle value for
-        // this field as json encoded string. This should be the best readable version of the value data.
-        if ((string)($theColConf['dbType'] ?? '') === 'json'
-            && ((is_string($value) && !str_starts_with($value, '{') && !str_starts_with($value, '['))
-                || !is_string($value))
-        ) {
-            // @todo Consider to pretty print the json value, as this would match the "human readable" goal.
-            $value = \json_encode($value);
-        }
-
         $l = '';
         $lang = static::getLanguageService();
         switch ((string)($theColConf['type'] ?? '')) {
@@ -1727,6 +1716,22 @@ class BackendUtility
                     }
                 }
                 break;
+            case 'json':
+                // For database type "JSON" the value in decoded state is most likely an array. This is not compatible with
+                // the "human-readable" processing and returning promise of this method. Thus, we ensure to handle value for
+                // this field as json encoded string. This should be the best readable version of the value data.
+                if (
+                    (
+                        is_string($value)
+                        && !str_starts_with($value, '{')
+                        && !str_starts_with($value, '[')
+                    )
+                    || !is_string($value)
+                ) {
+                    // @todo Consider to pretty print the json value, as this would match the "human readable" goal.
+                    $value = json_encode($value);
+                }
+                // no break intended.
             default:
                 if ($defaultPassthrough) {
                     $l = $value;
@@ -3461,17 +3466,14 @@ class BackendUtility
     public static function convertDatabaseRowValuesToPhp(string $table, array $row): array
     {
         $tableTca = $GLOBALS['TCA'][$table] ?? [];
-        if (!$tableTca) {
+        if (!is_array($tableTca) || $tableTca === []) {
             return $row;
         }
         $platform = static::getConnectionForTable($table)->getDatabasePlatform();
         foreach ($row as $field => $value) {
-            if (($tableTca['columns'][$field]['config']['type'] ?? '') === 'user') {
-                $dbType = $GLOBALS['TCA'][$table]['columns'][$field]['config']['dbType'] ?? '';
-                // @todo Only handle a specific dbType for now.
-                if ($dbType === 'json') {
-                    $row[$field] = Type::getType($dbType)->convertToPHPValue($value, $platform);
-                }
+            // @todo Only handle specific TCA type=json
+            if (($tableTca['columns'][$field]['config']['type'] ?? '') === 'json') {
+                $row[$field] = Type::getType('json')->convertToPHPValue($value, $platform);
             }
         }
         return $row;
diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/form-engine/element/json-element.js b/typo3/sysext/backend/Resources/Public/JavaScript/form-engine/element/json-element.js
new file mode 100644
index 0000000000000000000000000000000000000000..17bd3e435a3647ca3f1a3d9dda8d60f2a494c167
--- /dev/null
+++ b/typo3/sysext/backend/Resources/Public/JavaScript/form-engine/element/json-element.js
@@ -0,0 +1,13 @@
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+import{Resizable}from"@typo3/backend/form-engine/element/modifier/resizable.js";import{Tabbable}from"@typo3/backend/form-engine/element/modifier/tabbable.js";class JsonElement extends HTMLElement{constructor(){super(...arguments),this.element=null}connectedCallback(){this.element=document.getElementById(this.getAttribute("recordFieldId")||""),this.element&&(Resizable.enable(this.element),Tabbable.enable(this.element))}}window.customElements.define("typo3-formengine-element-json",JsonElement);
\ No newline at end of file
diff --git a/typo3/sysext/backend/Tests/Unit/Form/Element/JsonElementTest.php b/typo3/sysext/backend/Tests/Unit/Form/Element/JsonElementTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..486f6b2e6f45465c683da5f5a3d9e5957c1fcc60
--- /dev/null
+++ b/typo3/sysext/backend/Tests/Unit/Form/Element/JsonElementTest.php
@@ -0,0 +1,118 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Backend\Tests\Unit\Form\Element;
+
+use TYPO3\CMS\Backend\Form\Element\JsonElement;
+use TYPO3\CMS\Backend\Form\NodeExpansion\FieldInformation;
+use TYPO3\CMS\Backend\Form\NodeFactory;
+use TYPO3\CMS\Core\Cache\CacheManager;
+use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
+use TYPO3\CMS\Core\Imaging\IconFactory;
+use TYPO3\CMS\Core\Package\PackageManager;
+use TYPO3\CMS\Core\Page\JavaScriptModuleInstruction;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\T3editor\Mode;
+use TYPO3\CMS\T3editor\Registry\ModeRegistry;
+use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
+
+class JsonElementTest extends UnitTestCase
+{
+    protected bool $resetSingletonInstances = true;
+
+    /**
+     * @test
+     */
+    public function renderReturnsJsonInStandardTextarea(): void
+    {
+        $data = [
+                'parameterArray' => [
+                'itemFormElName' => 'config',
+                'itemFormElValue' => ['foo' => 'bar'],
+                'fieldConf' => [
+                    'config' => [
+                        'type' => 'json',
+                        'enableCodeEditor' => false,
+                        'placeholder' => 'placeholder',
+                    ],
+                ],
+            ],
+        ];
+
+        GeneralUtility::addInstance(IconFactory::class, $this->createMock(IconFactory::class));
+
+        $nodeFactoryMock = $this->createMock(NodeFactory::class);
+        $fieldInformationMock = $this->createMock(FieldInformation::class);
+        $fieldInformationMock->method('render')->willReturn(['html' => '']);
+        $nodeFactoryMock->method('create')->with(self::anything())->willReturn($fieldInformationMock);
+
+        $subject = new JsonElement($nodeFactoryMock, $data);
+        $result = $subject->render();
+
+        self::assertEquals('@typo3/backend/form-engine/element/json-element.js', $result['javaScriptModules'][0]->getName());
+        self::assertStringContainsString('<typo3-formengine-element-json', $result['html']);
+        self::assertStringContainsString('placeholder="placeholder"', $result['html']);
+        self::assertStringContainsString('&quot;foo&quot;: &quot;bar&quot;', $result['html']);
+    }
+
+    /**
+     * @test
+     */
+    public function renderReturnsJsonInCodeEditor(): void
+    {
+        $data = [
+            'tableName' => 'aTable',
+            'fieldName' => 'aField',
+            'parameterArray' => [
+                'itemFormElName' => 'config',
+                'itemFormElValue' => ['foo' => 'bar'],
+                'fieldConf' => [
+                    'config' => [
+                        'type' => 'json',
+                        'placeholder' => 'placeholder',
+                    ],
+                ],
+            ],
+        ];
+
+        GeneralUtility::addInstance(IconFactory::class, $this->createMock(IconFactory::class));
+        GeneralUtility::setSingletonInstance(PackageManager::class, $this->createMock(PackageManager::class));
+
+        $cacheManagerMock = $this->createMock(CacheManager::class);
+        $cacheMock = $this->createMock(FrontendInterface::class);
+        $cacheManagerMock->method('getCache')->with('assets')->willReturn($cacheMock);
+        $cacheMock->method('get')->withAnyParameters()->willReturn([]);
+        GeneralUtility::setSingletonInstance(CacheManager::class, $cacheManagerMock);
+
+        $modeRegistryMock = $this->createMock(ModeRegistry::class);
+        $modeRegistryMock->method('getDefaultMode')->willReturn(new Mode(JavaScriptModuleInstruction::create('foo')));
+        GeneralUtility::setSingletonInstance(ModeRegistry::class, $modeRegistryMock);
+
+        $nodeFactoryMock = $this->createMock(NodeFactory::class);
+        $fieldInformationMock = $this->createMock(FieldInformation::class);
+        $fieldInformationMock->method('render')->willReturn(['html' => '']);
+        $nodeFactoryMock->method('create')->with(self::anything())->willReturn($fieldInformationMock);
+
+        $subject = new JsonElement($nodeFactoryMock, $data);
+        $result = $subject->render();
+
+        self::assertEquals('@typo3/t3editor/element/code-mirror-element.js', $result['javaScriptModules'][0]->getName());
+        self::assertStringContainsString('<typo3-t3editor-codemirror', $result['html']);
+        self::assertStringContainsString('placeholder="placeholder"', $result['html']);
+        self::assertStringContainsString('&quot;foo&quot;: &quot;bar&quot;', $result['html']);
+    }
+}
diff --git a/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/TcaJsonTest.php b/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/TcaJsonTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..e464fdb661b3eba6fd441288eb4965d4b6118779
--- /dev/null
+++ b/typo3/sysext/backend/Tests/Unit/Form/FormDataProvider/TcaJsonTest.php
@@ -0,0 +1,241 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+namespace TYPO3\CMS\Backend\Tests\Unit\Form\FormDataProvider;
+
+use TYPO3\CMS\Backend\Form\FormDataProvider\TcaJson;
+use TYPO3\TestingFramework\Core\Unit\UnitTestCase;
+
+class TcaJsonTest extends UnitTestCase
+{
+    public function resultArrayDataProvider(): \Generator
+    {
+        yield 'Only handle new records' => [
+            [
+                'command' => 'edit',
+                'tableName' => 'aTable',
+                'databaseRow' => [
+                    'aField' => '{"foo":"bar"}',
+                ],
+                'processedTca' => [
+                    'columns' => [
+                        'aField' => [
+                            'config' => [
+                                'type' => 'json',
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+            [
+                'command' => 'edit',
+                'tableName' => 'aTable',
+                'databaseRow' => [
+                    'aField' => '{"foo":"bar"}',
+                ],
+                'processedTca' => [
+                    'columns' => [
+                        'aField' => [
+                            'config' => [
+                                'type' => 'json',
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+        ];
+        yield 'Only handle TCA type "json" records' => [
+            [
+                'command' => 'new',
+                'tableName' => 'aTable',
+                'databaseRow' => [
+                    'aField' => '{"foo":"bar"}',
+                ],
+                'processedTca' => [
+                    'columns' => [
+                        'aField' => [
+                            'config' => [
+                                'type' => 'text',
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+            [
+                'command' => 'new',
+                'tableName' => 'aTable',
+                'databaseRow' => [
+                    'aField' => '{"foo":"bar"}',
+                ],
+                'processedTca' => [
+                    'columns' => [
+                        'aField' => [
+                            'config' => [
+                                'type' => 'text',
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+        ];
+        yield 'Only handles string values' => [
+            [
+                'command' => 'new',
+                'tableName' => 'aTable',
+                'databaseRow' => [
+                    'aField' => ['foo' => 'bar'],
+                ],
+                'processedTca' => [
+                    'columns' => [
+                        'aField' => [
+                            'config' => [
+                                'type' => 'json',
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+            [
+                'command' => 'new',
+                'tableName' => 'aTable',
+                'databaseRow' => [
+                    'aField' => ['foo' => 'bar'],
+                ],
+                'processedTca' => [
+                    'columns' => [
+                        'aField' => [
+                            'config' => [
+                                'type' => 'json',
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+        ];
+        yield 'String values are properly decoded' => [
+            [
+                'command' => 'new',
+                'tableName' => 'aTable',
+                'databaseRow' => [
+                    'aField' => '{"foo":"bar"}',
+                ],
+                'processedTca' => [
+                    'columns' => [
+                        'aField' => [
+                            'config' => [
+                                'type' => 'json',
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+            [
+                'command' => 'new',
+                'tableName' => 'aTable',
+                'databaseRow' => [
+                    'aField' => ['foo' => 'bar'],
+                ],
+                'processedTca' => [
+                    'columns' => [
+                        'aField' => [
+                            'config' => [
+                                'type' => 'json',
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+        ];
+        yield 'Invalid values are handled properly' => [
+            [
+                'command' => 'new',
+                'tableName' => 'aTable',
+                'databaseRow' => [
+                    'aField' => '_-invalid-_',
+                ],
+                'processedTca' => [
+                    'columns' => [
+                        'aField' => [
+                            'config' => [
+                                'type' => 'json',
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+            [
+                'command' => 'new',
+                'tableName' => 'aTable',
+                'databaseRow' => [
+                    'aField' => [],
+                ],
+                'processedTca' => [
+                    'columns' => [
+                        'aField' => [
+                            'config' => [
+                                'type' => 'json',
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+        ];
+        yield 'Initialize empty values' => [
+            [
+                'command' => 'new',
+                'tableName' => 'aTable',
+                'databaseRow' => [
+                    'aField' => '',
+                ],
+                'processedTca' => [
+                    'columns' => [
+                        'aField' => [
+                            'config' => [
+                                'type' => 'json',
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+            [
+                'command' => 'new',
+                'tableName' => 'aTable',
+                'databaseRow' => [
+                    'aField' => [],
+                ],
+                'processedTca' => [
+                    'columns' => [
+                        'aField' => [
+                            'config' => [
+                                'type' => 'json',
+                            ],
+                        ],
+                    ],
+                ],
+            ],
+        ];
+    }
+
+    /**
+     * @test
+     * @dataProvider resultArrayDataProvider
+     */
+    public function addDataDoesHandleJsonRecords(array $input, array $expected): void
+    {
+        self::assertSame($expected, (new TcaJson())->addData($input));
+    }
+}
diff --git a/typo3/sysext/core/Classes/DataHandling/DataHandler.php b/typo3/sysext/core/Classes/DataHandling/DataHandler.php
index 29719bdc50f277d8f010ac6cc56e25fa52d2ddd6..e5e1b0c41498e692800479312999bcaf91eda019 100644
--- a/typo3/sysext/core/Classes/DataHandling/DataHandler.php
+++ b/typo3/sysext/core/Classes/DataHandling/DataHandler.php
@@ -1502,6 +1502,7 @@ class DataHandler implements LoggerAwareInterface
             'slug' => $this->checkValueForSlug((string)$value, $tcaFieldConf, $table, $id, (int)$realPid, $field, $additionalData['incomingFieldArray'] ?? []),
             'text' => $this->checkValueForText($value, $tcaFieldConf, $table, $realPid, $field),
             'group', 'folder', 'select' => $this->checkValueForGroupFolderSelect($res, $value, $tcaFieldConf, $table, $id, $status, $field),
+            'json' => $this->checkValueForJson($value, $tcaFieldConf),
             'passthrough', 'imageManipulation', 'user' => ['value' => $value],
             default => [],
         };
@@ -2268,6 +2269,42 @@ class DataHandler implements LoggerAwareInterface
         return $res;
     }
 
+    /**
+     * Evaluate "json" type values.
+     *
+     * @param array|string $value The value to set.
+     * @param array $tcaFieldConf Field configuration from TCA
+     * @return array The result array. The processed value (if any!) is set in the "value" key.
+     */
+    protected function checkValueForJson(array|string $value, array $tcaFieldConf): array
+    {
+        if (is_string($value)) {
+            if ($value === '') {
+                $value = [];
+            } else {
+                try {
+                    $value = json_decode($value, true, 512, JSON_THROW_ON_ERROR);
+                    if ($value === null) {
+                        // Unset value as it could not be decoded
+                        return [];
+                    }
+                } catch (\JsonException) {
+                    // Unset value as it is invalid
+                    return [];
+                }
+            }
+        }
+
+        if (!$this->validateValueForRequired($tcaFieldConf, $value)) {
+            // Unset value as it is required
+            return [];
+        }
+
+        return [
+            'value' => $value,
+        ];
+    }
+
     /**
      * Evaluates 'group', 'folder' or 'select' type values.
      *
@@ -7701,13 +7738,10 @@ class DataHandler implements LoggerAwareInterface
                 // Traverse array of values that was inserted into the database and compare with the actually stored value:
                 $errors = [];
                 foreach ($fieldArray as $key => $value) {
-                    $tcaColumnConfig = $tcaTableColumns[$key]['config'] ?? [];
-                    $columnType = $tcaColumnConfig['type'] ?? '';
-                    $columnDbType = $tcaColumnConfig['dbType'] ?? '';
                     if (!$this->checkStoredRecords_loose || $value || $row[$key]) {
                         // @todo Check explicitly for one type is fishy. However needed to avoid array to string
                         //       conversion errors. Find a better way do handle this.
-                        if ($columnType === 'user' && $columnDbType === 'json') {
+                        if (($tcaTableColumns[$key]['config']['type'] ?? '') === 'json') {
                             // To ensure a proper comparison we need to sort the array structure based on array keys
                             // in a recursive manner. Otherwise, we would emit an error just because the ordering was
                             // different. This must be done for value and the value in the row to be safe.
diff --git a/typo3/sysext/core/Classes/DataHandling/TableColumnType.php b/typo3/sysext/core/Classes/DataHandling/TableColumnType.php
index decd1894a050fe6888d4538e6053072d904698d6..be263688ba137d85e9ae3e397cdaf66015d7533c 100644
--- a/typo3/sysext/core/Classes/DataHandling/TableColumnType.php
+++ b/typo3/sysext/core/Classes/DataHandling/TableColumnType.php
@@ -50,6 +50,7 @@ final class TableColumnType extends Enumeration
     public const COLOR = 'COLOR';
     public const NUMBER = 'NUMBER';
     public const FILE = 'FILE';
+    public const JSON = 'JSON';
 
     /**
      * @param mixed $type
diff --git a/typo3/sysext/core/Classes/Database/Schema/DefaultTcaSchema.php b/typo3/sysext/core/Classes/Database/Schema/DefaultTcaSchema.php
index 42d54f703622f5b2fa9f054177fff03aed514e6b..e22d2838726acea992714732e2b7d250a7e6464a 100644
--- a/typo3/sysext/core/Classes/Database/Schema/DefaultTcaSchema.php
+++ b/typo3/sysext/core/Classes/Database/Schema/DefaultTcaSchema.php
@@ -422,87 +422,105 @@ class DefaultTcaSchema
                 $tables[$tablePosition]->addIndex(['t3ver_oid', 't3ver_wsid'], 't3ver_oid');
             }
 
+            // In the following, columns for TCA fields with a dedicated TCA type are
+            // added. In the unlikely case that no columns exist, we can skip the table.
+            if (!isset($tableDefinition['columns']) || !is_array($tableDefinition['columns'])) {
+                continue;
+            }
+
             // Add category fields for all tables, defining category columns (TCA type=category)
-            if (isset($tableDefinition['columns']) && is_array($tableDefinition['columns'])) {
-                foreach ($tableDefinition['columns'] as $fieldName => $fieldConfig) {
-                    if ((string)($fieldConfig['config']['type'] ?? '') !== 'category'
-                        || $this->isColumnDefinedForTable($tables, $tableName, $fieldName)
-                    ) {
-                        continue;
-                    }
+            foreach ($tableDefinition['columns'] as $fieldName => $fieldConfig) {
+                if ((string)($fieldConfig['config']['type'] ?? '') !== 'category'
+                    || $this->isColumnDefinedForTable($tables, $tableName, $fieldName)
+                ) {
+                    continue;
+                }
 
-                    if (($fieldConfig['config']['relationship'] ?? '') === 'oneToMany') {
-                        $tables[$tablePosition]->addColumn(
-                            $this->quote($fieldName),
-                            'text',
-                            [
-                                'notnull' => false,
-                            ]
-                        );
-                    } else {
-                        $tables[$tablePosition]->addColumn(
-                            $this->quote($fieldName),
-                            'integer',
-                            [
-                                'default' => 0,
-                                'notnull' => true,
-                                'unsigned' => true,
-                            ]
-                        );
-                    }
+                if (($fieldConfig['config']['relationship'] ?? '') === 'oneToMany') {
+                    $tables[$tablePosition]->addColumn(
+                        $this->quote($fieldName),
+                        'text',
+                        [
+                            'notnull' => false,
+                        ]
+                    );
+                } else {
+                    $tables[$tablePosition]->addColumn(
+                        $this->quote($fieldName),
+                        'integer',
+                        [
+                            'default' => 0,
+                            'notnull' => true,
+                            'unsigned' => true,
+                        ]
+                    );
                 }
             }
 
             // Add datetime fields for all tables, defining datetime columns (TCA type=datetime), except
             // those columns, which had already been added due to definition in "ctrl", e.g. "starttime".
-            if (isset($tableDefinition['columns']) && is_array($tableDefinition['columns'])) {
-                foreach ($tableDefinition['columns'] as $fieldName => $fieldConfig) {
-                    if ((string)($fieldConfig['config']['type'] ?? '') !== 'datetime'
-                        || $this->isColumnDefinedForTable($tables, $tableName, $fieldName)
-                    ) {
-                        continue;
-                    }
-
-                    if (in_array($fieldConfig['config']['dbType'] ?? '', QueryHelper::getDateTimeTypes(), true)) {
-                        $tables[$tablePosition]->addColumn(
-                            $this->quote($fieldName),
-                            $fieldConfig['config']['dbType'],
-                            [
-                                'notnull' => false,
-                            ]
-                        );
-                    } else {
-                        $tables[$tablePosition]->addColumn(
-                            $this->quote($fieldName),
-                            'integer',
-                            [
-                                'default' => 0,
-                                'notnull' => !($fieldConfig['config']['nullable'] ?? false),
-                                'unsigned' => false,
-                            ]
-                        );
-                    }
+            foreach ($tableDefinition['columns'] as $fieldName => $fieldConfig) {
+                if ((string)($fieldConfig['config']['type'] ?? '') !== 'datetime'
+                    || $this->isColumnDefinedForTable($tables, $tableName, $fieldName)
+                ) {
+                    continue;
                 }
-            }
-
-            // Add slug fields for all tables, defining slug columns (TCA type=slug)
-            if (isset($tableDefinition['columns']) && is_array($tableDefinition['columns'])) {
-                foreach ($tableDefinition['columns'] as $fieldName => $fieldConfig) {
-                    if ((string)($fieldConfig['config']['type'] ?? '') !== 'slug'
-                        || $this->isColumnDefinedForTable($tables, $tableName, $fieldName)
-                    ) {
-                        continue;
-                    }
 
+                if (in_array($fieldConfig['config']['dbType'] ?? '', QueryHelper::getDateTimeTypes(), true)) {
                     $tables[$tablePosition]->addColumn(
                         $this->quote($fieldName),
-                        'string',
+                        $fieldConfig['config']['dbType'],
                         [
-                            'length' => 2048,
                             'notnull' => false,
                         ]
                     );
+                } else {
+                    $tables[$tablePosition]->addColumn(
+                        $this->quote($fieldName),
+                        'integer',
+                        [
+                            'default' => 0,
+                            'notnull' => !($fieldConfig['config']['nullable'] ?? false),
+                            'unsigned' => false,
+                        ]
+                    );
+                }
+            }
+
+            // Add slug fields for all tables, defining slug columns (TCA type=slug)
+            foreach ($tableDefinition['columns'] as $fieldName => $fieldConfig) {
+                if ((string)($fieldConfig['config']['type'] ?? '') !== 'slug'
+                    || $this->isColumnDefinedForTable($tables, $tableName, $fieldName)
+                ) {
+                    continue;
+                }
+
+                $tables[$tablePosition]->addColumn(
+                    $this->quote($fieldName),
+                    'string',
+                    [
+                        'length' => 2048,
+                        'notnull' => false,
+                    ]
+                );
+            }
+
+            // Add json fields for all tables, defining json columns (TCA type=json)
+            foreach ($tableDefinition['columns'] as $fieldName => $fieldConfig) {
+                if ((string)($fieldConfig['config']['type'] ?? '') !== 'json'
+                    || $this->isColumnDefinedForTable($tables, $tableName, $fieldName)
+                ) {
+                    continue;
                 }
+
+                $tables[$tablePosition]->addColumn(
+                    $this->quote($fieldName),
+                    'json',
+                    [
+                        'default' => '[]',
+                        'notnull' => true,
+                    ]
+                );
             }
         }
 
diff --git a/typo3/sysext/core/Classes/Resource/Search/QueryRestrictions/SearchTermRestriction.php b/typo3/sysext/core/Classes/Resource/Search/QueryRestrictions/SearchTermRestriction.php
index 46170355d4e8f133cbf01edc2435dba6ff4bb4e4..8dcc458a1962113a2baec211ed84ddb1c109c139 100644
--- a/typo3/sysext/core/Classes/Resource/Search/QueryRestrictions/SearchTermRestriction.php
+++ b/typo3/sysext/core/Classes/Resource/Search/QueryRestrictions/SearchTermRestriction.php
@@ -108,6 +108,7 @@ class SearchTermRestriction implements QueryRestrictionInterface
                 // Assemble the search condition only if the field makes sense to be searched
                 if ($fieldType === 'text'
                     || $fieldType === 'flex'
+                    || $fieldType === 'json'
                     || $fieldType === 'email'
                     || $fieldType === 'link'
                     || $fieldType === 'color'
diff --git a/typo3/sysext/core/Configuration/DefaultConfiguration.php b/typo3/sysext/core/Configuration/DefaultConfiguration.php
index e73ed8e7b6f21ab79def63d7c88700ee7af24381..0e6a4e8620f31a7af6fef62e8bea9af5c03bea34 100644
--- a/typo3/sysext/core/Configuration/DefaultConfiguration.php
+++ b/typo3/sysext/core/Configuration/DefaultConfiguration.php
@@ -597,10 +597,15 @@ return [
                             \TYPO3\CMS\Backend\Form\FormDataProvider\TcaFlexProcess::class,
                         ],
                     ],
+                    \TYPO3\CMS\Backend\Form\FormDataProvider\TcaJson::class => [
+                        'depends' => [
+                            \TYPO3\CMS\Backend\Form\FormDataProvider\TcaText::class,
+                        ],
+                    ],
                     \TYPO3\CMS\Backend\Form\FormDataProvider\TcaRadioItems::class => [
                         'depends' => [
                             \TYPO3\CMS\Backend\Form\FormDataProvider\InitializeProcessedTca::class,
-                            \TYPO3\CMS\Backend\Form\FormDataProvider\TcaText::class,
+                            \TYPO3\CMS\Backend\Form\FormDataProvider\TcaJson::class,
                         ],
                     ],
                     \TYPO3\CMS\Backend\Form\FormDataProvider\TcaCheckboxItems::class => [
@@ -842,6 +847,11 @@ return [
                             \TYPO3\CMS\Backend\Form\FormDataProvider\SiteResolving::class,
                         ],
                     ],
+                    \TYPO3\CMS\Backend\Form\FormDataProvider\TcaJson::class => [
+                        'depends' => [
+                            \TYPO3\CMS\Backend\Form\FormDataProvider\TcaText::class,
+                        ],
+                    ],
                     \TYPO3\CMS\Backend\Form\FormDataProvider\TcaRadioItems::class => [
                         'depends' => [
                             \TYPO3\CMS\Backend\Form\FormDataProvider\SiteResolving::class,
@@ -927,11 +937,16 @@ return [
                             \TYPO3\CMS\Backend\Form\FormDataProvider\TcaColumnsRemoveUnused::class,
                         ],
                     ],
-                    \TYPO3\CMS\Backend\Form\FormDataProvider\TcaRadioItems::class => [
+                    \TYPO3\CMS\Backend\Form\FormDataProvider\TcaJson::class => [
                         'depends' => [
                             \TYPO3\CMS\Backend\Form\FormDataProvider\TcaText::class,
                         ],
                     ],
+                    \TYPO3\CMS\Backend\Form\FormDataProvider\TcaRadioItems::class => [
+                        'depends' => [
+                            \TYPO3\CMS\Backend\Form\FormDataProvider\TcaJson::class,
+                        ],
+                    ],
                     \TYPO3\CMS\Backend\Form\FormDataProvider\TcaCheckboxItems::class => [
                         'depends' => [
                             \TYPO3\CMS\Backend\Form\FormDataProvider\TcaColumnsRemoveUnused::class,
diff --git a/typo3/sysext/core/Documentation/Changelog/12.1/Feature-99226-IntroduceDbTypeJsonForTCATypeUser.rst b/typo3/sysext/core/Documentation/Changelog/12.1/Feature-99226-IntroduceDbTypeJsonForTCATypeUser.rst
index 0b9f44980db814f9ffd8e4b00a47f1172ebbd061..03f462263fad270f53f3e4c775a09eb9f7c80c6c 100644
--- a/typo3/sysext/core/Documentation/Changelog/12.1/Feature-99226-IntroduceDbTypeJsonForTCATypeUser.rst
+++ b/typo3/sysext/core/Documentation/Changelog/12.1/Feature-99226-IntroduceDbTypeJsonForTCATypeUser.rst
@@ -8,6 +8,14 @@ Feature: #99226 - Introduce dbType json for TCA type user
 
 See :issue:`99226`
 
+
+.. attention::
+
+    This TCA option is **no longer available**! It has been
+    :ref:`replaced <important-100088-1677950866>` by the dedicated
+    :ref:`json <feature-100088-1677965005>` TCA type. Do not use
+    this option in your installation, but use the new TCA type.
+
 Description
 ===========
 
diff --git a/typo3/sysext/core/Documentation/Changelog/12.3/Feature-100088-NewTCATypeJson.rst b/typo3/sysext/core/Documentation/Changelog/12.3/Feature-100088-NewTCATypeJson.rst
new file mode 100644
index 0000000000000000000000000000000000000000..6512c6d5a96a57226d66a78bbcca635d7b1c51c4
--- /dev/null
+++ b/typo3/sysext/core/Documentation/Changelog/12.3/Feature-100088-NewTCATypeJson.rst
@@ -0,0 +1,58 @@
+.. include:: /Includes.rst.txt
+
+.. _feature-100088-1677965005:
+
+======================================
+Feature: #100088 - New TCA type "json"
+======================================
+
+See :issue:`100088`
+
+Description
+===========
+
+In our effort of introducing dedicated TCA types for special use cases,
+a new TCA field type called :php:`json` has been added to TYPO3 Core.
+Its main purpose is to simplify the TCA configuration when working with
+fields, containing JSON data. It therefore :ref:`replaces <important-100088-1677950866>`
+the previously introduced :php:`dbtype=json` of TCA type :php:`user`.
+
+Using the new type, TYPO3 automatically takes care of adding the corresponding
+database column.
+
+The TCA type :php:`json` features the following column configuration:
+
+- :php:`behaviour`: :php:`allowLanguageSynchronization`
+- :php:`cols`
+- :php:`default`
+- :php:`enableCodeEditor`
+- :php:`fieldControl`
+- :php:`fieldInformation`
+- :php:`fieldWizard`
+- :php:`placeholder`
+- :php:`readOnly`
+- :php:`required`
+- :php:`rows`
+
+.. note::
+
+    In case :php:`enableCodeEditor` is set to :php:`true`, which is the default
+    and the system extension `t3editor` is installed and active, the JSON value
+    is rendered in the corresponding code editor. Otherwise it is rendered in a
+    standard `textarea` HTML element.
+
+The following column configuration can be overwritten by Page TSconfig:
+
+- :typoscript:`cols`
+- :typoscript:`rows`
+- :typoscript:`readOnly`
+
+
+
+Impact
+======
+
+It's now possible to use a dedicated TCA type for rendering of JSON fields.
+Using the new TCA type, corresponding database columns are added automatically.
+
+.. index:: Backend, PHP-API, TCA, ext:backend
diff --git a/typo3/sysext/core/Documentation/Changelog/12.3/Important-100088-RemoveDbTypeJsonForTCATypeUser.rst b/typo3/sysext/core/Documentation/Changelog/12.3/Important-100088-RemoveDbTypeJsonForTCATypeUser.rst
new file mode 100644
index 0000000000000000000000000000000000000000..2da9b3e1196238786161eb097753a3c4cf342582
--- /dev/null
+++ b/typo3/sysext/core/Documentation/Changelog/12.3/Important-100088-RemoveDbTypeJsonForTCATypeUser.rst
@@ -0,0 +1,48 @@
+.. include:: /Includes.rst.txt
+
+.. _important-100088-1677950866:
+
+=========================================================
+Important: #100088 - Remove dbType json for TCA type user
+=========================================================
+
+See :issue:`100088`
+
+Description
+===========
+
+With :issue:`99226` the `dbType=json` option has been added for
+TCA type `user`. After some reconsideration, it has been decided
+to drop this option again in favor of the dedicated TCA type `json`.
+Have a look to the according :ref:`changelog <feature-100088-1677965005>`
+for further information.
+
+Since the `dbType` option has not been released in any LTS version yet,
+the option is dropped without further deprecation. Also no TCA migration
+is applied.
+
+In case you make already use of this `dbType` in your custom extension,
+you need to migrate to the new TCA type.
+
+Example:
+
+..  code-block:: php
+
+    // Before
+    'myField' => [
+        'config' => [
+            'type' => 'user',
+            'renderType' => 'myRenderType',
+            'dbType' => 'json',
+        ],
+    ],
+
+    // After
+    'myField' => [
+        'config' => [
+            'type' => 'json',
+            'renderType' => 'myRenderType',
+        ],
+    ],
+
+.. index:: Backend, PHP-API, TCA, ext:backend
diff --git a/typo3/sysext/core/Tests/Unit/DataHandling/DataHandlerTest.php b/typo3/sysext/core/Tests/Unit/DataHandling/DataHandlerTest.php
index 3a90eb3168e2979124cc6765ee6d45aee2d1996c..734abd345c949274bda52ba4d2271d698beefeb8 100644
--- a/typo3/sysext/core/Tests/Unit/DataHandling/DataHandlerTest.php
+++ b/typo3/sysext/core/Tests/Unit/DataHandling/DataHandlerTest.php
@@ -1059,6 +1059,42 @@ class DataHandlerTest extends UnitTestCase
         self::assertSame($expectedResult, $this->subject->_call('checkValueForInput', null, ['type' => 'input', 'max' => 40], 'tt_content', 'NEW55c0e67f8f4d32.04974534', 89, 'table_caption'));
     }
 
+    public function checkValueForJsonDataProvider(): \Generator
+    {
+        yield 'Converts empty string to array' => [
+            '',
+            ['value' => []],
+        ];
+        yield 'Handles invalid JSON' => [
+            '_-invalid-_',
+            [],
+        ];
+        yield 'Decodes JSON' => [
+            '{"foo":"bar"}',
+            ['value' => ['foo' => 'bar']],
+        ];
+        yield 'Array is not decoded' => [
+            ['foo' => 'bar'],
+            ['value' => ['foo' => 'bar']],
+        ];
+    }
+
+    /**
+     * @test
+     * @dataProvider checkValueForJsonDataProvider
+     */
+    public function checkValueForJson(string|array $input, array $expected): void
+    {
+        self::assertSame(
+            $expected,
+            $this->subject->_call(
+                'checkValueForJson',
+                $input,
+                ['type' => 'json']
+            )
+        );
+    }
+
     /**
      * @test
      * @dataProvider referenceValuesAreCastedDataProvider
diff --git a/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/DataMapFactoryTest.php b/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/DataMapFactoryTest.php
index aafc403c4ea45ab7d4a03fe13ade1554c0c68c3e..a9d19203f5f80ddd39236da2e5b153c360e64186 100644
--- a/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/DataMapFactoryTest.php
+++ b/typo3/sysext/extbase/Tests/Unit/Persistence/Generic/Mapper/DataMapFactoryTest.php
@@ -463,6 +463,7 @@ class DataMapFactoryTest extends UnitTestCase
             [['type' => 'color'], TableColumnType::COLOR],
             [['type' => 'number'], TableColumnType::NUMBER],
             [['type' => 'file'], TableColumnType::FILE],
+            [['type' => 'json'], TableColumnType::JSON],
         ];
     }
 
diff --git a/typo3/sysext/lowlevel/Classes/Controller/DatabaseIntegrityController.php b/typo3/sysext/lowlevel/Classes/Controller/DatabaseIntegrityController.php
index b6154a126240dbcd31d868b5101fb7eebb1208d9..c919db7627561317cabb326fbb71d0566eacc60c 100644
--- a/typo3/sysext/lowlevel/Classes/Controller/DatabaseIntegrityController.php
+++ b/typo3/sysext/lowlevel/Classes/Controller/DatabaseIntegrityController.php
@@ -928,6 +928,7 @@ class DatabaseIntegrityController
                     case 'link':
                     case 'password':
                     case 'color':
+                    case 'json':
                     default:
                         $fields['type'] = 'text';
                 }
@@ -2264,6 +2265,7 @@ class DatabaseIntegrityController
                         case 'link':
                         case 'password':
                         case 'color':
+                        case 'json':
                         default:
                             $this->fields[$fieldName]['type'] = 'text';
                     }
diff --git a/typo3/sysext/reactions/Classes/Form/Element/FieldMapElement.php b/typo3/sysext/reactions/Classes/Form/Element/FieldMapElement.php
index 6475950e22ed923c265b5f135353b85bb9154df2..0f73eb0f810bbbe70262667379993c1499c2d508 100644
--- a/typo3/sysext/reactions/Classes/Form/Element/FieldMapElement.php
+++ b/typo3/sysext/reactions/Classes/Form/Element/FieldMapElement.php
@@ -22,7 +22,7 @@ use TYPO3\CMS\Backend\Form\Element\AbstractFormElement;
 /**
  * Creates a dynamic element to add values to table fields.
  *
- * This is rendered for config type=user, renderType=fieldMap
+ * This is rendered for config type=json, renderType=fieldMap
  *
  * @internal This is a specific hook implementation and is not considered part of the Public TYPO3 API.
  */
diff --git a/typo3/sysext/reactions/Configuration/TCA/Overrides/sys_reaction_create_record.php b/typo3/sysext/reactions/Configuration/TCA/Overrides/sys_reaction_create_record.php
index c9adbb89e56082dc73ab6ea2dcf9c3fd7f6daaba..ec99b2b2677b4248132e64e85c5b6ec63b666b0b 100644
--- a/typo3/sysext/reactions/Configuration/TCA/Overrides/sys_reaction_create_record.php
+++ b/typo3/sysext/reactions/Configuration/TCA/Overrides/sys_reaction_create_record.php
@@ -18,10 +18,8 @@
             'description' => 'LLL:EXT:reactions/Resources/Private/Language/locallang_db.xlf:sys_reaction.fields.description',
             'displayCond' => 'FIELD:table_name:REQ:true',
             'config' => [
-                'type' => 'user',
+                'type' => 'json',
                 'renderType' => 'fieldMap',
-                'dbType' => 'json',
-                'default' => '{}',
             ],
         ],
     ]
diff --git a/typo3/sysext/reactions/ext_tables.sql b/typo3/sysext/reactions/ext_tables.sql
index e235882ddc8d897c2a21758e62c17fff2141dec8..87fc55ea9df2d1ec48804e0a3efa8598b91d96eb 100644
--- a/typo3/sysext/reactions/ext_tables.sql
+++ b/typo3/sysext/reactions/ext_tables.sql
@@ -9,7 +9,6 @@ CREATE TABLE sys_reaction (
 	impersonate_user int(11) unsigned DEFAULT '0' NOT NULL,
 	table_name varchar(255) DEFAULT '' NOT NULL,
 	storage_pid int(11) unsigned DEFAULT '0' NOT NULL,
-	fields json NOT NULL,
 
 	UNIQUE identifier_key (identifier),
 	KEY index_source (reaction_type(5))
diff --git a/typo3/sysext/t3editor/Configuration/Backend/T3editor/Modes.php b/typo3/sysext/t3editor/Configuration/Backend/T3editor/Modes.php
index ce387d59d1097cb6e35c6e2c2d5789c2b32512ba..8db36582ffc6d2e13779aa4af08843ce56486e2e 100644
--- a/typo3/sysext/t3editor/Configuration/Backend/T3editor/Modes.php
+++ b/typo3/sysext/t3editor/Configuration/Backend/T3editor/Modes.php
@@ -19,6 +19,10 @@ return [
         'module' => JavaScriptModuleInstruction::create('@codemirror/lang-javascript', 'javascript')->invoke(),
         'extensions' => ['javascript'],
     ],
+    'json' => [
+        'module' => JavaScriptModuleInstruction::create('@codemirror/lang-json', 'json')->invoke(),
+        'extensions' => ['json'],
+    ],
     'php' => [
         'module' => JavaScriptModuleInstruction::create('@codemirror/lang-php', 'php')->invoke(),
         'extensions' => ['php', 'php5', 'php7', 'phps'],
diff --git a/typo3/sysext/t3editor/Resources/Public/JavaScript/element/code-mirror-element.js b/typo3/sysext/t3editor/Resources/Public/JavaScript/element/code-mirror-element.js
index 040021b701af1d05f44d5b208d6ecbf652fa9d4d..ed24d362c792883fe31890e2b242761ac0058ec6 100644
--- a/typo3/sysext/t3editor/Resources/Public/JavaScript/element/code-mirror-element.js
+++ b/typo3/sysext/t3editor/Resources/Public/JavaScript/element/code-mirror-element.js
@@ -10,11 +10,11 @@
  *
  * The TYPO3 project - inspiring people to share!
  */
-var __decorate=function(e,t,o,r){var i,l=arguments.length,n=l<3?t:null===r?r=Object.getOwnPropertyDescriptor(t,o):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,o,r);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(n=(l<3?i(n):l>3?i(t,o,n):i(t,o))||n);return l>3&&n&&Object.defineProperty(t,o,n),n};import{LitElement,html,css}from"lit";import{customElement,property,state}from"lit/decorators.js";import{EditorView,lineNumbers,highlightSpecialChars,drawSelection,keymap}from"@codemirror/view";import{EditorState}from"@codemirror/state";import{syntaxHighlighting,defaultHighlightStyle}from"@codemirror/language";import{defaultKeymap,indentWithTab}from"@codemirror/commands";import{oneDark}from"@codemirror/theme-one-dark";import{executeJavaScriptModuleInstruction,loadModule,resolveSubjectRef}from"@typo3/core/java-script-item-processor.js";import"@typo3/backend/element/spinner-element.js";let CodeMirrorElement=class extends LitElement{constructor(){super(...arguments),this.mode=null,this.addons=[],this.keymaps=[],this.lineDigits=0,this.autoheight=!1,this.nolazyload=!1,this.readonly=!1,this.fullscreen=!1,this.panel="bottom",this.editorView=null}render(){return html`
+var __decorate=function(e,t,r,o){var i,l=arguments.length,n=l<3?t:null===o?o=Object.getOwnPropertyDescriptor(t,r):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,o);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(n=(l<3?i(n):l>3?i(t,r,n):i(t,r))||n);return l>3&&n&&Object.defineProperty(t,r,n),n};import{LitElement,html,css}from"lit";import{customElement,property,state}from"lit/decorators.js";import{EditorView,lineNumbers,highlightSpecialChars,drawSelection,keymap,placeholder}from"@codemirror/view";import{EditorState}from"@codemirror/state";import{syntaxHighlighting,defaultHighlightStyle}from"@codemirror/language";import{defaultKeymap,indentWithTab}from"@codemirror/commands";import{oneDark}from"@codemirror/theme-one-dark";import{executeJavaScriptModuleInstruction,loadModule,resolveSubjectRef}from"@typo3/core/java-script-item-processor.js";import"@typo3/backend/element/spinner-element.js";let CodeMirrorElement=class extends LitElement{constructor(){super(...arguments),this.mode=null,this.addons=[],this.keymaps=[],this.lineDigits=0,this.autoheight=!1,this.nolazyload=!1,this.readonly=!1,this.fullscreen=!1,this.panel="bottom",this.editorView=null}render(){return html`
       <div id="codemirror-parent" @keydown=${e=>this.onKeydown(e)}></div>
       ${this.label?html`<div class="panel panel-${this.panel}">${this.label}</div>`:""}
       ${null===this.editorView?html`<typo3-backend-spinner size="large" variant="dark"></typo3-backend-spinner>`:""}
-    `}firstUpdated(){if(this.nolazyload)return void this.initializeEditor(this.firstElementChild);const e={root:document.body};let t=new IntersectionObserver((e=>{e.forEach((e=>{e.intersectionRatio>0&&(t.unobserve(e.target),this.firstElementChild&&"textarea"===this.firstElementChild.nodeName.toLowerCase()&&this.initializeEditor(this.firstElementChild))}))}),e);t.observe(this)}onKeydown(e){e.ctrlKey&&e.altKey&&"f"===e.key&&(e.preventDefault(),this.fullscreen=!0),"Escape"===e.key&&this.fullscreen&&(e.preventDefault(),this.fullscreen=!1)}async initializeEditor(e){const t=EditorView.updateListener.of((t=>{t.docChanged&&(e.value=t.state.doc.toString(),e.dispatchEvent(new CustomEvent("change",{bubbles:!0})))}));this.lineDigits>0?this.style.setProperty("--rows",this.lineDigits.toString()):e.getAttribute("rows")&&this.style.setProperty("--rows",e.getAttribute("rows"));const o=[oneDark,t,lineNumbers(),highlightSpecialChars(),drawSelection(),EditorState.allowMultipleSelections.of(!0),syntaxHighlighting(defaultHighlightStyle,{fallback:!0})];if(this.readonly&&o.push(EditorState.readOnly.of(!0)),this.mode){const e=await executeJavaScriptModuleInstruction(this.mode);o.push(...e)}this.addons.length>0&&o.push(...await Promise.all(this.addons.map((e=>executeJavaScriptModuleInstruction(e)))));const r=[...defaultKeymap,indentWithTab];if(this.keymaps.length>0){const e=await Promise.all(this.keymaps.map((e=>loadModule(e).then((t=>resolveSubjectRef(t,e))))));e.forEach((e=>r.push(...e)))}o.push(keymap.of(r)),this.editorView=new EditorView({state:EditorState.create({doc:e.value,extensions:o}),parent:this.renderRoot.querySelector("#codemirror-parent"),root:this.renderRoot})}};CodeMirrorElement.styles=css`
+    `}firstUpdated(){if(this.nolazyload)return void this.initializeEditor(this.firstElementChild);const e={root:document.body};let t=new IntersectionObserver((e=>{e.forEach((e=>{e.intersectionRatio>0&&(t.unobserve(e.target),this.firstElementChild&&"textarea"===this.firstElementChild.nodeName.toLowerCase()&&this.initializeEditor(this.firstElementChild))}))}),e);t.observe(this)}onKeydown(e){e.ctrlKey&&e.altKey&&"f"===e.key&&(e.preventDefault(),this.fullscreen=!0),"Escape"===e.key&&this.fullscreen&&(e.preventDefault(),this.fullscreen=!1)}async initializeEditor(e){const t=EditorView.updateListener.of((t=>{t.docChanged&&(e.value=t.state.doc.toString(),e.dispatchEvent(new CustomEvent("change",{bubbles:!0})))}));this.lineDigits>0?this.style.setProperty("--rows",this.lineDigits.toString()):e.getAttribute("rows")&&this.style.setProperty("--rows",e.getAttribute("rows"));const r=[oneDark,t,lineNumbers(),highlightSpecialChars(),drawSelection(),EditorState.allowMultipleSelections.of(!0),syntaxHighlighting(defaultHighlightStyle,{fallback:!0})];if(this.readonly&&r.push(EditorState.readOnly.of(!0)),this.placeholder&&r.push(placeholder(this.placeholder)),this.mode){const e=await executeJavaScriptModuleInstruction(this.mode);r.push(...e)}this.addons.length>0&&r.push(...await Promise.all(this.addons.map((e=>executeJavaScriptModuleInstruction(e)))));const o=[...defaultKeymap,indentWithTab];if(this.keymaps.length>0){const e=await Promise.all(this.keymaps.map((e=>loadModule(e).then((t=>resolveSubjectRef(t,e))))));e.forEach((e=>o.push(...e)))}r.push(keymap.of(o)),this.editorView=new EditorView({state:EditorState.create({doc:e.value,extensions:r}),parent:this.renderRoot.querySelector("#codemirror-parent"),root:this.renderRoot})}};CodeMirrorElement.styles=css`
     :host {
       display: flex;
       flex-direction: column;
@@ -77,4 +77,4 @@ var __decorate=function(e,t,o,r){var i,l=arguments.length,n=l<3?t:null===r?r=Obj
       border-bottom-width: 1px;
       order: -1;
     }
-  `,__decorate([property({type:Object})],CodeMirrorElement.prototype,"mode",void 0),__decorate([property({type:Array})],CodeMirrorElement.prototype,"addons",void 0),__decorate([property({type:Array})],CodeMirrorElement.prototype,"keymaps",void 0),__decorate([property({type:Number})],CodeMirrorElement.prototype,"lineDigits",void 0),__decorate([property({type:Boolean,reflect:!0})],CodeMirrorElement.prototype,"autoheight",void 0),__decorate([property({type:Boolean})],CodeMirrorElement.prototype,"nolazyload",void 0),__decorate([property({type:Boolean})],CodeMirrorElement.prototype,"readonly",void 0),__decorate([property({type:Boolean,reflect:!0})],CodeMirrorElement.prototype,"fullscreen",void 0),__decorate([property({type:String})],CodeMirrorElement.prototype,"label",void 0),__decorate([property({type:String})],CodeMirrorElement.prototype,"panel",void 0),__decorate([state()],CodeMirrorElement.prototype,"editorView",void 0),CodeMirrorElement=__decorate([customElement("typo3-t3editor-codemirror")],CodeMirrorElement);export{CodeMirrorElement};
\ No newline at end of file
+  `,__decorate([property({type:Object})],CodeMirrorElement.prototype,"mode",void 0),__decorate([property({type:Array})],CodeMirrorElement.prototype,"addons",void 0),__decorate([property({type:Array})],CodeMirrorElement.prototype,"keymaps",void 0),__decorate([property({type:Number})],CodeMirrorElement.prototype,"lineDigits",void 0),__decorate([property({type:Boolean,reflect:!0})],CodeMirrorElement.prototype,"autoheight",void 0),__decorate([property({type:Boolean})],CodeMirrorElement.prototype,"nolazyload",void 0),__decorate([property({type:Boolean})],CodeMirrorElement.prototype,"readonly",void 0),__decorate([property({type:Boolean,reflect:!0})],CodeMirrorElement.prototype,"fullscreen",void 0),__decorate([property({type:String})],CodeMirrorElement.prototype,"label",void 0),__decorate([property({type:String})],CodeMirrorElement.prototype,"placeholder",void 0),__decorate([property({type:String})],CodeMirrorElement.prototype,"panel",void 0),__decorate([state()],CodeMirrorElement.prototype,"editorView",void 0),CodeMirrorElement=__decorate([customElement("typo3-t3editor-codemirror")],CodeMirrorElement);export{CodeMirrorElement};
\ No newline at end of file