Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
json-edit-react
Advanced tools
A React component for editing or viewing JSON/object data
Features include:
npm i json-edit-react
or
yarn add json-edit-react
import { JsonEditor } from 'json-edit-react'
// In your React components:
<JsonEditor data={ myDataObject } { ...props }>
(for end user)
It's pretty self explanatory (click the "edit" icon to edit, etc.), but there are a few not-so-obvious ways of interacting with the editor:
Cmd/Ctrl/Shift-Enter
to add a new line (Enter
submits the value)Enter
for new line, and Cmd/Ctrl/Shift-Enter
for submitEscape
to cancel editingCmd/Ctrl
will copy the path to the selected node rather than its valueThe only required value is data
.
prop | type | default | description |
---|---|---|---|
data | object|array | The data to be displayed / edited | |
rootName | string | "data" | A name to display in the editor as the root of the data object. |
onUpdate | UpdateFunction | A function to run whenever a value is updated (edit, delete or add) in the editor. See Update functions. | |
onUpdate | UpdateFunction | A function to run whenever a value is edited. | |
onDelete | UpdateFunction | A function to run whenever a value is deleted. | |
onAdd | UpdateFunction | A function to run whenever a new property is added. | |
enableClipboard | boolean|CopyFunction | true | Whether or not to enable the "Copy to clipboard" button in the UI. If a function is provided, true is assumed and this function will be run whenever an item is copied. |
indent | number | 4 | Specify the amount of indentation for each level of nesting in the displayed data. |
collapse | boolean|number|FilterFunction | false | Defines which nodes of the JSON tree will be displayed "opened" in the UI on load. If boolean , it'll be either all or none. A number specifies a nesting depth after which nodes will be closed. For more fine control a function can be provided — see Filter functions. |
restrictEdit | boolean|FilterFunction | false | If false , no editing is permitted. A function can be provided for more specificity — see Filter functions |
restrictDelete | boolean|FilterFunction | false | As with restrictEdit but for deletion |
restrictAdd | boolean|FilterFunction | false | As with restrictEdit but for adding new properties |
keySort | boolean|CompareFunction | false | If true , object keys will be ordered (using default JS .sort() ). A compare function can also be provided to define sorting behaviour. |
showArrayIndices | boolean | true | Whether or not to display the index (as a property key) for array elements. |
defaultValue | any | null | When a new property is added, it is initialised with this value. |
stringTruncate | number | 250 | String values longer than this many characters will be displayed truncated (with ... ). The full string will always be visible when editing. |
translations | LocalisedStrings object | { } | UI strings (such as error messages) can be translated by passing an object containing localised string values (there are only a few). See Localisation |
theme | string|ThemeObject|[string, ThemeObject] | "default" | Either the name of one of the built-in themes, or an object specifying some or all theme properties. See Themes. |
className | string | Name of a CSS class to apply to the component. In most cases, specifying theme properties will be more straightforward. | |
icons | {[iconName]: JSX.Element, ... } | { } | Replace the built-in icons by specifying them here. See Themes. |
minWidth | number|string (CSS value) | 250 | Minimum width for the editor container. |
maxWidth | number|string (CSS value) | 600 | Maximum width for the editor container. |
A callback to be executed whenever a data update (edit, delete or add) occurs can be provided. You might wish to use this to update some state, or make an API call, for example. If you want the same function for all updates, then just the onUpdate
prop is sufficient. However, should you require something different for editing, deletion and addition, then you can provide separate Update functions via the onEdit
, onDelete
and onAdd
props.
The function will receive the following object as a parameter:
{
newData, // data state after update
currentData, // data state before update
newValue, // the new value of the property being updated
currentValue, // the current value of the property being updated
name, // name of the property being updated
path // full path to the property being updated, as an array of property keys
// (e.g. [ "user", "friends", 1, "name" ] ) (equivalent to "user.friends[1].name")
}
The function needn't return anything, but if it returns false
, it will be considered an error, in which case an error message will displayed in the UI and the internal data state won't actually be updated. If the return value is a string
, this will be the error message displayed (i.e. you can define your own error messages for updates).
A similar callback is executed whenever an item is copied to the clipboard (if passed to the enableClipboard
prop), but with a different input parameter:
key: // name of the property being copied
path: // path to the property
value: // the value copied to the clipboard (Note: this value will be serialised to a string)
type: // Either "path" or "value" depending on whether "Cmd/Ctrl" was pressed
Since there is very little user feedback when clicking "Copy", a good idea would be to present some kind of notification in this callback.
You can control which nodes of the data structure can be edited, deleted, or added to by passing Filter functions. These will be called on each property in the data and the attribute will be enforced depending on whether the function returns true
or false
(true
means cannot be edited).
The function receives the following object:
{
key, // name of the property
path, // path to the property (as an array of property keys)
level, // depth of the property (with 0 being the root)
value, // value of the property
size // if a collection (object, array), the number of items (null for non-collections)
}
A Filter function is available for the collapse
prop as well, so you can have your data appear with deeply-nested collections opened up, while collapsing everything else, for example.
// in <JsonEditor /> props
restrictEdit = { ({ level }) => level === 0 }
id
field be edited:restrictEdit = { ({ key }) => key === "id" }
// You'd probably want to include this in `restrictDelete` as well
restrictDelete = { ({ size }) => size !== null }
restrictAdd = { ({ key }) => key !== "address" && key !== "users" }
// "Adding" is irrelevant for non-collection nodes
There is a small selection of built-in themes (as seen in the Demo app). In order to use one of these, just pass the name into the theme
prop (although realistically, these exist more to showcase the capabilities — I'm open to better built-in themes, so feel free to create an issue with suggestions). The available themes are:
default
githubDark
githubLight
monoDark
monoLight
candyWrapper
psychedelic
However, you can pass in your own theme object, or part thereof. The theme structure is as follows (this is the "default" theme definition):
{
displayName: 'Default',
fragments: { edit: 'rgb(42, 161, 152)' },
styles: {
container: {
backgroundColor: '#f6f6f6',
fontFamily: 'monospace',
},
property: '#292929',
bracket: { color: 'rgb(0, 43, 54)', fontWeight: 'bold' },
itemCount: { color: 'rgba(0, 0, 0, 0.3)', fontStyle: 'italic' },
string: 'rgb(203, 75, 22)',
number: 'rgb(38, 139, 210)',
boolean: 'green',
null: { color: 'rgb(220, 50, 47)', fontVariant: 'small-caps', fontWeight: 'bold' },
input: ['#292929', { fontSize: '90%' }],
inputHighlight: '#b3d8ff',
error: { fontSize: '0.8em', color: 'red', fontWeight: 'bold' },
iconCollection: 'rgb(0, 43, 54)',
iconEdit: 'edit',
iconDelete: 'rgb(203, 75, 22)',
iconAdd: 'edit',
iconCopy: 'rgb(38, 139, 210)',
iconOk: 'green',
iconCancel: 'rgb(203, 75, 22)',
},
}
The styles
property is the main one to focus on. Each key (property
, bracket
, itemCount
) refers to a part of the UI. The value for each key is either a string
, in which case it is interpreted as the colour (or background colour in the case of container
and inputHighlight
), or a full CSS style object for fine-grained definition. You only need to provide properties you wish to override —— all unspecified ones will fallback to either the default theme, or another theme that you specify as the "base".
For example, if you want to use the "githubDark" theme, but just change a couple of small things, you'd specify something like this:
// in <JsonEditor /> props
theme={[
'githubDark',
{
iconEdit: 'grey',
boolean: { color: 'red', fontStyle: 'italic', fontWeight: 'bold', fontSize: '80%' },
},
]}
Which would change the "Edit" icon and boolean values from this:
into this:
Or you could create your own theme from scratch and overwrite the whole theme object.
So, to summarise, the theme
prop can take either:
"candyWrapper"
fragments
, styles
, displayName
etc., or just the styles
part (at the root level)[ "<themeName>, {...overrides } ]
You can play round with live editing of the themes in the Demo app by selecting "Edit this theme!" from the "Demo data" selector.
The fragments
property above is just a convenience to allow repeated style "fragments" to be defined once and referred to using an alias. For example, if you wanted all your icons to be blue and slightly larger and spaced out, you might define a fragment like so:
fragments: { iconAdjust: { color: "blue", fontSize: "110%", marginRight: "0.6em" }}
Then in the theme object, just use:
{
...,
iconEdit: "iconAdjust",
iconDelete: "iconAdjust",
iconAdd: "iconAdjust",
iconCopy: "iconAdjust",
}
Then, when you want to tweak it later, you only need to update it in one place!
Fragments can also be mixed with additional properties, and even other fragments, like so:
iconEdit: [ "iconAdjust", "anotherFragment", { marginLeft: "1em" } ]
Internally, all sizing and spacing is done in em
s, never px
. This makes scaling a lot easier — just change the font-size of the main container (either via the className
prop or in the container
prop of the theme) (or its parent), and watch the whole component scale accordingly.
The default icons can be replaced, but you need to provide them as React/HTML elements. Just define any or all of them within the icons
prop, keyed as follows:
icons={{
add: <YourIcon />
edit: <YourIcon />
delete: <YourIcon />
copy: <YourIcon />
ok: <YourIcon />
cancel: <YourIcon />
chevron: <YourIcon />
}}
The Icon components will need to have their own styles defined, as the theme styles won't be added to the custom elements.
Localise your implementation by passing in a translations
object to replace the default strings. The keys and default (English) values are as follows:
{
ITEM_SINGLE: '{{count}} item',
ITEMS_MULTIPLE: '{{count}} items',
KEY_NEW: 'Enter new key',
ERROR_KEY_EXISTS: 'Key already exists',
ERROR_INVALID_JSON: 'Invalid JSON',
ERROR_UPDATE: 'Update unsuccessful',
ERROR_DELETE: 'Delete unsuccessful',
ERROR_ADD: 'Adding node unsuccessful',
}
Even though Undo/Redo functionality is probably desirable in most cases, this is not built in to the component, for two main reasons:
Please open an issue: https://github.com/CarlosNZ/json-edit-react/issues
The main features I'd like to introduce are:
FAQs
React component for editing or viewing JSON/object data
The npm package json-edit-react receives a total of 24,488 weekly downloads. As such, json-edit-react popularity was classified as popular.
We found that json-edit-react demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.