Notes of Maks Nemisj

Experiments with JavaScript

JSON.parse welcome to my consciousness

Today JSON is widely used in different corners of software development. It’s used as data format, as configuration or even as in memory database. At my current company we also use it as configuration format. The more I use it, the more I have feeling that it’s “a bit” inconsistent and “raw”. You would expect that it would be enough to do JSON.parse(str) and all problems solved, but that’s not true. Read further to find out the real truth.

json-safe-parse

First thing which is weird is the fact that JSON allows you to override inherited properties of the Native Object object. I will not go deeper into this topic, but thanks to the library json-safe-parse, we can sleep well and don’t thik of this problem anymore. If you want to read more about the problem, read library’s documentation.
Next.

Objects

You know what JSON stands for, right? It is “JavaScript Object Notation”. Which is, in my opinion, means that JSON should represent an object, like {}, [] or null. At least this is what I was thinking until a couple of days ago, when I found out truth. It appeared that there are not only arrays, objects and null values, which can be parsed by json, but also something else. Let’s have a look at the following code snippet and think what would it give us?

const zero = JSON.parse('0');
const truth = JSON.parse('true');

When executing following code I found out that "zero" variable will be a real 0 number and truth variable will be a real boolean true. This brings the following statement: number values and booleans are also part of the JSON spec. What makes sense, since in JavaScript, everything is an object, right? But it’s not quite like that for JSON.parse. At the same time, empty string – "" – is NOT a valid JSON.

JSON.parse(''); will happily throw an Error and it is something what brings BIG confusion into my head!!! Why? Because, now to parse JSON configuration, I need to think in “special-cases”.Let’s have a look.

We use JSON as a configuration object and store it as a string in the DB. Imagine now that someone will put 'true' into the field wher JSON is stored. In the code, which will parse that json, parser will not throw any error, since the JSON.parse("true") is a valid bit. Though later on somewhere in the code it could through an error, since it’s a different type. Imagine now, that there is a 'null' value going to be in DB. In that case JSON.parse("null") could lead to errors at even more places, e.g. when using Object.keys(json). It’s not possible to enumerate null values, so it will just break. But that’s not all. Don’t forget about empty strings, which are not empty – " " which will pass logical if – if (str !== '').

All this brought me to the next snippet which I now use when I want to parse JSON into configuration object:

First of all, it’s always checking that the parsed json is an object object. Secondly it dismisses empty strings or null values, since it’s not misconfiguration, but merely an emptiness of configuration. As last it trims empty strings, since it’s possible to have value like " ", which is just should be ignored.

, , ,

2 thoughts on “JSON.parse welcome to my consciousness

  • Clem says:

    If you want to check if JSON main element is an object before parse you can simply test the first char:

    function parseJsonObject(str){
        if(!(str.trimLeft()[0] === "{")){
            throw('It is not an object')
        }
        return parse(str)
    }
    
  • Maks Nemisj says:

    @Clem, true, but maybe I wasn’t clear enough in my article. It’s not only about JSON being an object. It’s about parsing of the empty strings and returning empty object if str is not defined. You see, I have more concrete case than only checking if it’s an object or not, since for my case, empty string shouldn’t throw any error.

Leave a Reply

Your email address will not be published. Required fields are marked *