ngrx-store-localstorage
ngrx-store-localstorage copied to clipboard
JSON.parse throwing error for invalid JSON not handled
If local storage contains invalid JSON object, for example {hello":"world"}, JSON.parse throws an error which is not handled by ngrx-store-localstorage. Should this error be handled within the library or should it be responsibility of the user of the library?
Unhandled Promise rejection: Unexpected token a in JSON at position 1 ; Zone: <root> ; Task: Promise.then ; Value: SyntaxError: Unexpected token a in JSON at position 1
Affects [email protected] with Google Chrome version 67.0.3396.99.
One way to solve this issue would be to allow user to pass custom json parsing function to the library.
You can specify the JSON parsing function when specifying the state key in the configuration as an object passed to the localStorageSync
. You must pass a serialize
and deserialize
function to accomplish this as follow:
localStorageSync({
"keys": [
{
"greeting": {
"serialize": myJsonSerializer,
"deserialize": myJsonDeserializer
}
},
{...},
...
]
})
I also thought so but it seems that the raw data is put through JSON.parse before deserializer is called, therefore it will still give an error even if I give it my own jsonDeserializer.
https://github.com/btroncone/ngrx-store-localstorage/blob/master/src/index.ts
starting from line 92:
const isObjectRegex = new RegExp('{|\\[');
let raw = stateSlice;
if (stateSlice === 'null' || isObjectRegex.test(stateSlice.charAt(0))) {
raw = JSON.parse(stateSlice, reviver);
}
return Object.assign({}, acc, {
[key]: deserialize ? deserialize(raw) : raw
});
I got your point, but if you see closer to the lines 127, then the 183, you can see that first serialize then stringify and then when retrieving the state, should do the inverse and it's what you point out: parse then deserialize. Somehow the string-stored state is being corrupted or you're generating a string by yourself from an object (then passing the condition in line 181), which is why is not a parseable JSON.
https://github.com/btroncone/ngrx-store-localstorage/blob/c3954e29a006e185402d22f2e5a5439bf19c504b/src/index.ts#L127
https://github.com/btroncone/ngrx-store-localstorage/blob/c3954e29a006e185402d22f2e5a5439bf19c504b/src/index.ts#L183
https://github.com/btroncone/ngrx-store-localstorage/blob/c3954e29a006e185402d22f2e5a5439bf19c504b/src/index.ts#L181
Yes, the string in local storage was corrupted by a user (using browser dev tools) which then caused JSON.parse to throw error and the whole application not to work.
So if I want to store my data as JSON string in local storage, there is no way to avoid this issue. This is because of condition isObjectRegex.test(stateSlice.charAt(0))
so no matter if I pass deserializer or not, JSON.parse will be called and it will fail. It seems that the library trusts that the data coming from outside is actually valid json, which is a problem in itself. Unless I am missing something...
any toughs @btroncone ?