Coder Social home page Coder Social logo

json-stringify-safe's Introduction

json-stringify-safe

Like JSON.stringify, but doesn't throw on circular references.

Usage

Takes the same arguments as JSON.stringify.

var stringify = require('json-stringify-safe');
var circularObj = {};
circularObj.circularRef = circularObj;
circularObj.list = [ circularObj, circularObj ];
console.log(stringify(circularObj, null, 2));

Output:

{
  "circularRef": "[Circular]",
  "list": [
    "[Circular]",
    "[Circular]"
  ]
}

Details

stringify(obj, serializer, indent, decycler)

The first three arguments are the same as to JSON.stringify. The last is an argument that's only used when the object has been seen already.

The default decycler function returns the string '[Circular]'. If, for example, you pass in function(k,v){} (return nothing) then it will prune cycles. If you pass in function(k,v){ return {foo: 'bar'}}, then cyclical objects will always be represented as {"foo":"bar"} in the result.

stringify.getSerialize(serializer, decycler)

Returns a serializer that can be used elsewhere. This is the actual function that's passed to JSON.stringify.

Note that the function returned from getSerialize is stateful for now, so do not use it more than once.

json-stringify-safe's People

Contributors

isaacs avatar mikeal avatar moll avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

json-stringify-safe's Issues

I get a syntax error

OS: Arch
Node Version: v16.3.0
Json-stringify-safe vesion: 5.0.1
Parent pakage: Request

Error

node_modules/json-stringify-safe/stringify.js:19
            var thisPos = stack.indexOf(this) ~thisPos ? stack.splice(thisPos + 1) : stack.push(this) ~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key)
                                              ^

SyntaxError: Unexpected token '~'

Weird part:
It works fine on windows but not on linux.

Typescript support

I wrote some typings for use in our own project, I don't have time to create a PR but I felt like dropping them here:

declare module 'json-stringify-safe' {
    namespace stringify {
        export type CycleReplacer = (key: string, value: any) => string;
        export type Replacer = (key: string, value: any) => any;

        export function getSerialize(replacer?: Replacer, cycleReplacer?: CycleReplacer): any;
    }

    function stringify(
        obj: object,
        replacer?: stringify.Replacer,
        space?: string | number,
        cycleReplacer?: stringify.CycleReplacer,
    ): string;

    export = stringify;
}

.indexOf() is undefined in IE8

Tried to use this with browserify, and it started throwing errors in IE8 because .indexOf() is not defined. I shimmed it in my project, but maybe it should be shimmed here?

bower.json

Make a bower.json with a main property. This will make this library work properly using bower and grunt wiredep.

Stringify on XMLHttpRequest

In a framework I'm working on, we're seeing people try to log requests that are in progress, which causes an InvalidStateError: DOM Exception 11 to be thrown. While I'm not a fan of logging these requests, it seems it would be preferable to handle such a case gracefully. Temporarily I've added a check around the class and readystate, which works, but feels like a hack. Any opinions?

Array replacer raises an error

The documentations says:

The first three arguments are the same as to JSON.stringify.

But when I try to pass an array of strings as the second parameter, the module raises an error:

> var object = { a: 'b', c: 'd' }
undefined
> stringify(object, ['a'])
TypeError: undefined is not a function
    at Object.<anonymous> (/node_modules/json-stringify-safe/stringify.js:25:48)
    at Object.stringify (native)
    at stringify (/node_modules/json-stringify-safe/stringify.js:5:15)
    at repl:1:11
    at REPLServer.defaultEval (repl.js:132:27)
    at bound (domain.js:254:14)
    at REPLServer.runBound [as eval] (domain.js:267:12)
    at REPLServer.<anonymous> (repl.js:279:12)
    at REPLServer.emit (events.js:107:17)
    at REPLServer.Interface._onLine (readline.js:214:10)

The same argument works with JSON.stringify:

> JSON.stringify(object, ['a'])
'{"a":"b"}'

Very deep objects take a long time to stringify, maybe add a `depth` option ?

I've been trying to log some objects that are very deep, but I'm actually not interested in the full object, just the parts that are not at a too big depth.

I know the current implementation relies on JSON.stringify, which has no depth option, so I'm not sure if it is possible to implement it from here.

Anyway, here's a code sample to reproduce :

  var rootFoo = [];
  var foo = rootFoo;
  for (var j = 0; j < 1000; j++) {
    foo[j] = [];
    for (var i = 0; i < 100; i++) {
      foo[j][i] = foo;
    }
    foo = foo[j]
  }

  process.stdout.write(require("json-stringify-safe")(rootFoo) + "\n");

Typo in package description

The description for this repo has a typo in it:

Like JSON.stringify, but doens't throw on circular references

It should be:

Like JSON.stringify, but doesn't throw on circular references

false positive for sibling (not-circular) references

var safeStringify = require('json-stringify-safe')

var obj = { foo: 'bar' };

console.log(safeStringify({
    a: obj,
    b: obj
}));


console.log(JSON.stringify({
    a: obj,
    b: obj
}));

Will produce the following ouput:

{"a":{"foo":"bar"},"b":"[Circular ~.a]"}
{"a":{"foo":"bar"},"b":{"foo":"bar"}}

It seems to identify multiple sibling references to the same object as circulars.

comparison is not good enough

i tried to replace request's toJSON with this and I get "RangeError: Maximum call stack size exceeded".

I'm 99% sure it's in the indexOf comparison not being good enough to match objects. Something like underscore's isEqual deep comparison might fix this.

No lock file found in the jsonstringifysafe project on Tag: v5.0.1

Issue: There is no package-lock.json or npm-shrinkwrap.json file uploaded to the GitHub repository https://github.com/isaacs/json-stringify-safe

Questions: We are conducting a research study on the lock files used in JS projects. We were curious:

  1. Will you upload any lock files to GitHub as recommended above? (Yes/No), and why?:
  2. Do you have any additional comments? (If so, please write it down):

For any publication or research report based on this study, we will share all responses from developers in an anonymous way. Both your projects and personal information will be kept confidential.

Rationale: NPM introduced package-lock.json and npm-shrimpwrap.json files to capture the exact dependency tree installed at any point in time. When package.json defines the required dependencies and their respective versions using semantic versioning (e.g., “express”: “^4.16.4”), npm always downloads the latest version of packages to satisfy the specified version ranges (e.g., 4.17.1)[1]. If the latest version of any package keeps changing and has backward incompatibility issues with previous versions, the project may have an inconsistent running environment and get intermittent failures. In such scenarios, it can be very difficult for developers to debug programs and settle down the software environment [2].

List of Risks:

  • Nondeterministic package downloads and installations across different environments [3]
  • Produce irreproducible builds [4]
  • Inconsistent results of program execution [5]

Suggested Solution: Please fixate the dependencies by either specifying the exact library version in the package.json file or by uploading the package-lock.json or npm-shrinkwrap.json file to GitHub.

References:
https://docs.npmjs.com/cli/v7/configuring-npm/package-lock-json
https://blog.logrocket.com/why-you-should-use-package-lock-json/
2019. 10 npm Security Best Practices. https://snyk.io/blog/ten-npm-security-best-practices/.
Pronnoy Goswami, Saksham Gupta, Zhiyuan Li, Na Meng, and Daphne Yao. 2020. Investigating The Reproducibility of NPM Packages. In2020 IEEE International
2021. Npm Security Best Practices. https://bytesafe.dev/posts/npm-security-best-practices/#no9-deterministic-results.

can cause unexpected behaviour in the presence of __defineGetter__

Thanks for sharing!

I came across an error while trying to calculate the hash of a sequelize query object. It includes model definitions, which contain a reference to the client, which contains a reference to pg which does lazy instantiation using __defineGetter__ on the pg-native library (that I don't need so don't have installed).

Open question what the correct behaviour should be here. You could argue that lazy require via a getter is an abberant special case that could be covered by a workaround, or you could take the view that stringification should be "as is" rather than running arbitrary code.

I think I'm in the former camp, as "normal" getter use would probably be expected behaviour, but wanted to post this here to document the error case.

Maybe a compromise might be to allow an optional getterReplacer that decides behaviour

Allow to pass object to fromJSON

Use case scenario:

Server renders:

<script>
window.__PRELOADED_STATE__ = ${transit.toJSON(preloadedState)};
</script>

Client picks up __PRELOADED_STATE__, which is a valid JSON, therefore it is converted to an object. To use it, I need to cast it back to string, e.g.

console.log('window.__PRELOADED_STATE__', transit.fromJSON(JSON.stringify(window.__PRELOADED_STATE__)));

error during npm i

$ npm i
events.js:183░░░░░░⸩ ⠼ extract:json-stringify-safe: sill extract [email protected]
      throw er; // Unhandled 'error' event
      ^

Error: write after end
    at writeAfterEnd (_stream_writable.js:236:12)
    at PassThrough.Writable.write (_stream_writable.js:287:5)
    at PassThrough.Writable.end (_stream_writable.js:563:10)
    at ReadEntry.entry.on (/Users/username/.nvm/versions/node/v8.11.1/lib/node_modules/npm/node_modules/pacote/lib/extract-stream.js:19:41)
    at emitOne (events.js:121:20)
    at ReadEntry.emit (events.js:211:7)
    at ReadEntry.emit (/Users/username/.nvm/versions/node/v8.11.1/lib/node_modules/npm/node_modules/tar/node_modules/minipass/index.js:296:25)
    at ReadEntry.[maybeEmitEnd] (/Users/username/.nvm/versions/node/v8.11.1/lib/node_modules/npm/node_modules/tar/node_modules/minipass/index.js:249:12)
    at ReadEntry.end (/Users/username/.nvm/versions/node/v8.11.1/lib/node_modules/npm/node_modules/tar/node_modules/minipass/index.js:162:27)
    at Unpack.[consumeBody] (/Users/username/.nvm/versions/node/v8.11.1/lib/node_modules/npm/node_modules/tar/lib/parse.js:210:13)
    at Unpack.[consumeChunkSub] (/Users/username/.nvm/versions/node/v8.11.1/lib/node_modules/npm/node_modules/tar/lib/parse.js:391:40)
    at Unpack.[consumeChunk] (/Users/username/.nvm/versions/node/v8.11.1/lib/node_modules/npm/node_modules/tar/lib/parse.js:362:30)
    at Unzip.(anonymous function).on.chunk (/Users/username/.nvm/versions/node/v8.11.1/lib/node_modules/npm/node_modules/tar/lib/parse.js:291:59)
    at emitOne (events.js:116:13)
    at Unzip.emit (events.js:211:7)
    at Unzip.emit (/Users/username/.nvm/versions/node/v8.11.1/lib/node_modules/npm/node_modules/tar/node_modules/minipass/index.js:296:25)
events.js:183░░░░░░⸩ ⠼ extract:fclone: sill extract [email protected]
      throw er; // Unhandled 'error' event
      ^

Error: write after end
    at writeAfterEnd (_stream_writable.js:236:12)
    at PassThrough.Writable.write (_stream_writable.js:287:5)
    at PassThrough.Writable.end (_stream_writable.js:563:10)
    at ReadEntry.entry.on (/Users/username/.nvm/versions/node/v8.11.1/lib/node_modules/npm/node_modules/pacote/lib/extract-stream.js:19:41)
    at emitOne (events.js:121:20)
    at ReadEntry.emit (events.js:211:7)
    at ReadEntry.emit (/Users/username/.nvm/versions/node/v8.11.1/lib/node_modules/npm/node_modules/tar/node_modules/minipass/index.js:296:25)
    at ReadEntry.[maybeEmitEnd] (/Users/username/.nvm/versions/node/v8.11.1/lib/node_modules/npm/node_modules/tar/node_modules/minipass/index.js:249:12)
    at ReadEntry.end (/Users/username/.nvm/versions/node/v8.11.1/lib/node_modules/npm/node_modules/tar/node_modules/minipass/index.js:162:27)
    at Unpack.[consumeBody] (/Users/username/.nvm/versions/node/v8.11.1/lib/node_modules/npm/node_modules/tar/lib/parse.js:210:13)
    at Unpack.[consumeChunkSub] (/Users/username/.nvm/versions/node/v8.11.1/lib/node_modules/npm/node_modules/tar/lib/parse.js:391:40)
    at Unpack.[consumeChunk] (/Users/username/.nvm/versions/node/v8.11.1/lib/node_modules/npm/node_modules/tar/lib/parse.js:362:30)
    at Unzip.(anonymous function).on.chunk (/Users/username/.nvm/versions/node/v8.11.1/lib/node_modules/npm/node_modules/tar/lib/parse.js:291:59)
    at emitOne (events.js:116:13)
    at Unzip.emit (events.js:211:7)
    at Unzip.emit (/Users/username/.nvm/versions/node/v8.11.1/lib/node_modules/npm/node_modules/tar/node_modules/minipass/index.js:296:25)
npm WARN [email protected] No repository field.

npm ERR! cancel after 1 retries!

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/username/.npm/_logs/2018-05-19T19_35_09_875Z-debug.log

BigInt serialisation

Fails to stringify if object has a bigInt

var jsonStringifySafe require('json-stringify-safe');
var v = {t: BigInt(0)}
jsonStringifySafe(v);

>>> Do not know how to serialize a BigInt

feature request: deserialize

It would be good to be able to not only stringify an object with circular references using this lib but also deserialize the obtained string, obtaining an object being the same as the original object (another object in JS memory but with the same values and references working in the same way).

Something like parse in this https://github.com/WebReflection/flatted

I request a feature here because https://github.com/WebReflection/flatted creates a string which is not so easy to read for humans.

Slow when processing arrays

Here is the code for performing the benchmark:

var Bench = require('bench');
var Stringify = require('json-stringify-safe');

var list = [];
for (var i = 0; i < 10000; ++i ) {
    list.push({'some' : 'thing'});
}

exports.compare = {
    'safe stringify' : function () {

        return Stringify(list);
    },
    'stringify' : function () {

        return JSON.stringify(list);
    }
};

Bench.runMain();

Here is the result:

Winner: stringify
Compared with next highest (safe stringify), it's:
98.6% faster
71.4 times as fast
1.85 order(s) of magnitude faster
A LOT FASTER

When list is only 100 items the result is:

Winner: stringify
Compared with next highest (safe stringify), it's:
56.19% faster
2.28 times as fast
0.36 order(s) of magnitude faster
QUITE A BIT FASTER

RangeError: Maximum call stack size exceeded

This breaks with any Backbone view (I assume an example of a common type of object). For example, with backbone, in Chrome, in the console:

safeStringify = require('safe-json-stringify')
m = new Backbone.Model
v = new Backbone.View({ model: m })
safeStringify(v)

Throws an error, "RangeError: Maximum call stack size exceeded"

With the model (m), interestingly, it doesn't throw an error, but it writes an empty object, "{}".

Is this supposed to work only on simple objects, not instances of pseudo-classes?

Thanks

Missing semicolon breaks JS obfuscation

It appears to me that you have to terminate every statement before the unary ~ operator. Otherwise you will end up having syntax errors if you remove the newlines from the code.

I don't want to start a flamewar about semicolons being good or bad, I just see that in this case, line 18 & 19 should be ending with semicolons, otherwise the code breaks if you use webpack-js-obfuscator.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.