Research
Security News
Quasar RAT Disguised as an npm Package for Detecting Vulnerabilities in Ethereum Smart Contracts
Socket researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
safe-json-value
Advanced tools
⛑️ JSON serialization should never fail.
Please reach out if you're looking for a Node.js API or CLI engineer (11 years of experience). Most recently I have been Netlify Build's and Netlify Plugins' technical lead for 2.5 years. I am available for full-time remote positions.
Prevent JSON.stringify()
from:
import safeJsonValue from 'safe-json-value'
const input = { one: true }
input.self = input
JSON.stringify(input) // Throws due to cycle
const { value, changes } = safeJsonValue(input)
JSON.stringify(value) // '{"one":true}"
console.log(changes) // List of changed properties
// [
// {
// path: ['self'],
// oldValue: <ref *1> { one: true, self: [Circular *1] },
// newValue: undefined,
// reason: 'unsafeCycle'
// }
// ]
npm install safe-json-value
This package works in both Node.js >=18.18.0 and browsers.
This is an ES module. It must be loaded using
an import
or import()
statement,
not require()
. If TypeScript is used, it must be configured to
output ES modules,
not CommonJS.
value
any
options
Options?
Return value: object
Makes value
JSON-safe by:
JSON.stringify()
JSON.stringify()
This never throws.
Object with the following properties.
Type: number
Default: 1e7
Big JSON strings can make a process, filesystem operation or network request
crash. maxSize
prevents it by setting a maximum
JSON.stringify(value).length
.
Additional properties beyond the size limit are omitted. They are completely removed, not truncated (including strings).
const input = { one: true, two: 'a'.repeat(1e6) }
JSON.stringify(safeJsonValue(input, { maxSize: 1e5 }).value) // '{"one":true}"
Type: boolean
Default: false
If false
, object/array properties are processed recursively. Please note that
cycles are not removed when this is true
.
Object with the following properties.
Type: any
Copy of the input value
after applying all the changes to make
it JSON-safe.
The top-level value
itself might be changed (including to undefined
) if it
is either invalid JSON or has a toJSON()
method.
The value
is not serialized to a JSON string. This allows choosing the
serialization format (JSON, YAML, etc.), processing the value, etc.
Type: Change[]
List of changes applied to value
. Each item is an
individual change to a specific property. A given property might have multiple
changes, listed in order.
Type: Array<string | symbol | number>
Property path.
Type: any
Property value before the change.
Type: any
Property value after the change. undefined
means the property was omitted.
Type: string
Reason for the change among:
"unsafeCycle"
,
"unsafeBigInt"
, "unsafeSize"
,
"unsafeException"
,
"unsafeToJSON"
,
"unsafeGetter"
"descriptorNotWritable"
,
"descriptorNotConfigurable"
"unstableInfinite"
"ignoredFunction"
,
"ignoredUndefined"
, "ignoredSymbolValue"
,
"ignoredSymbolKey"
,
"ignoredNotEnumerable"
,
"ignoredArrayProperty"
"unresolvedToJSON"
,
"unresolvedClass"
, "unresolvedGetter"
Type: Error?
Error that triggered the change. Only present if reason
is
"unsafeException"
,
"unsafeToJSON"
or
"unsafeGetter"
.
This is a list of all possible changes applied to make the value JSON-safe.
JSON.stringify()
can throw on specific properties. Those are omitted.
const input = { one: true }
input.self = input
JSON.stringify(input) // Throws due to cycle
JSON.stringify(safeJsonValue(input).value) // '{"one":true}"
const input = { toJSON: () => ({ one: true, input }) }
JSON.stringify(input) // Throws due to infinite `toJSON()` recursion
JSON.stringify(safeJsonValue(input).value) // '{"one":true,"input":{...}}"
const input = { one: true, two: 0n }
JSON.stringify(input) // Throws due to BigInt
JSON.stringify(safeJsonValue(input).value) // '{"one":true}"
const input = { one: true, two: '\n'.repeat(5e8) }
JSON.stringify(input) // Throws due to max string length
JSON.stringify(safeJsonValue(input).value) // '{"one":true}"
toJSON()
const input = {
one: true,
two: {
toJSON: () => {
throw new Error('example')
},
},
}
JSON.stringify(input) // Throws due to `toJSON()`
JSON.stringify(safeJsonValue(input).value) // '{"one":true}"
const input = {
one: true,
get two() {
throw new Error('example')
},
}
JSON.stringify(input) // Throws due to `get two()`
JSON.stringify(safeJsonValue(input).value) // '{"one":true}"
const input = new Proxy(
{ one: false },
{
get: () => {
throw new Error('example')
},
},
)
JSON.stringify(input) // Throws due to proxy
JSON.stringify(safeJsonValue(input).value) // '{}'
const input = {}
Object.defineProperty(input, 'one', {
value: true,
enumerable: true,
writable: false,
configurable: true,
})
input.one = false // Throws: non-writable
const safeInput = safeJsonValue(input).value
safeInput.one = false // Does not throw: now writable
const input = {}
Object.defineProperty(input, 'one', {
value: true,
enumerable: true,
writable: true,
configurable: false,
})
// Throws: non-configurable
Object.defineProperty(input, 'one', { value: false, enumerable: false })
const safeInput = safeJsonValue(input).value
// Does not throw: now configurable
Object.defineProperty(safeInput, 'one', { value: false, enumerable: false })
JSON.stringify()
changes the types of specific values unexpectedly. Those are
omitted.
const input = { one: true, two: Number.NaN, three: Number.POSITIVE_INFINITY }
JSON.stringify(input) // '{"one":true,"two":null,"three":null}"
JSON.stringify(safeJsonValue(input).value) // '{"one":true}"
const input = [true, undefined, Symbol(), false]
JSON.stringify(input) // '[true, null, null, false]'
JSON.stringify(safeJsonValue(input).value) // '[true, false]'
JSON.stringify()
omits some specific types. Those are omitted right away to
prevent any unexpected output.
const input = { one: true, two: () => {} }
JSON.parse(JSON.stringify(input)) // { one: true }
safeJsonValue(input).value // { one: true }
undefined
const input = { one: true, two: undefined }
JSON.parse(JSON.stringify(input)) // { one: true }
safeJsonValue(input).value // { one: true }
const input = { one: true, two: Symbol() }
JSON.parse(JSON.stringify(input)) // { one: true }
safeJsonValue(input).value // { one: true }
const input = { one: true, [Symbol()]: true }
JSON.parse(JSON.stringify(input)) // { one: true }
safeJsonValue(input).value // { one: true }
const input = { one: true }
Object.defineProperty(input, 'two', { value: true, enumerable: false })
JSON.parse(JSON.stringify(input)) // { one: true }
safeJsonValue(input).value // { one: true }
const input = [true]
input.prop = true
JSON.parse(JSON.stringify(input)) // [true]
safeJsonValue(input).value // [true]
JSON.stringify()
can transform some values. Those are resolved right away to
prevent any unexpected output.
toJSON()
const input = {
toJSON: () => ({ one: true }),
}
JSON.parse(JSON.stringify(input)) // { one: true }
safeJsonValue(input).value // { one: true }
const input = { one: new Date() }
JSON.parse(JSON.stringify(input)) // { one: '2022-07-29T14:37:40.865Z' }
safeJsonValue(input).value // { one: '2022-07-29T14:37:40.865Z' }
const input = { one: new Set([]) }
JSON.parse(JSON.stringify(input)) // { one: {} }
safeJsonValue(input).value // { one: {} }
const input = {
get one() {
return true
},
}
JSON.parse(JSON.stringify(input)) // { one: true }
safeJsonValue(input).value // { one: true }
const input = new Proxy(
{ one: false },
{
get: () => true,
},
)
JSON.parse(JSON.stringify(input)) // { one: true }
safeJsonValue(input).value // { one: true }
is-json-value
: Check if a value
is valid JSONtruncate-json
: Truncate a JSON
stringguess-json-indent
: Guess the
indentation of a JSON stringerror-serializer
: Convert
errors to/from plain objectsFor any question, don't hesitate to submit an issue on GitHub.
Everyone is welcome regardless of personal background. We enforce a Code of conduct in order to promote a positive and inclusive environment.
This project was made with ❤️. The simplest way to give back is by starring and sharing it online.
If the documentation is unclear or has a typo, please click on the page's Edit
button (pencil icon) and suggest a correction.
If you would like to help us fix a bug or add a new feature, please check our guidelines. Pull requests are welcome!
ehmicky 💻 🎨 🤔 📖 | Pedro Augusto de Paula Barbosa 📖 |
FAQs
⛑️ JSON serialization should never fail
The npm package safe-json-value receives a total of 1,682 weekly downloads. As such, safe-json-value popularity was classified as popular.
We found that safe-json-value demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer 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 researchers uncover a malicious npm package posing as a tool for detecting vulnerabilities in Etherium smart contracts.
Security News
Research
A supply chain attack on Rspack's npm packages injected cryptomining malware, potentially impacting thousands of developers.
Research
Security News
Socket researchers discovered a malware campaign on npm delivering the Skuld infostealer via typosquatted packages, exposing sensitive data.