Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-95324

JSON.stringify: replacer's `this` value is not conforming

    XMLWordPrintable

Details

    • All
    • 4c930247e (dev), d7602cb31 (6.5)

    Description

      Summary

      In JSON.stringify implementation, replacer function's this value is not set to a containing object as required by specs (and implemented in all other engines).

      Description

      Long story short, JSON.stringify takes optional second argument which can be a replacer function. It is supposed to be called for each encountered key-value during serialization. While replacer's second argument is already serialized (so you could just return it), just in case you are not satisfied with default serialization — the original value is still passed in together with the whole object as a value of javascript this.

      Expected behavior (Alternatives)

      WebKit defines it as follow:

      You can provide an optional replacer method. It will be passed the
      key and value of each member, with this bound to the containing
      object. The value that is returned from your method will be
      serialized. If your method returns undefined, then the member will
      be excluded from the serialization.

      MDN defines it as follow:

      As a function, it takes two parameters: the key and the value being stringified. The object in which the key was found is provided as the replacer's this parameter.

      Actual behavior

      Qt/QML V4 engine, however, violates this twice at once:

      1. this is set to a new object with a value for an empty ("") key;
      2. value on this is the same already toJSON() serialized value as the second argument.

      …which is kinda defeats the purpose, and buggy as hell. I wonder, how it happened that no tests exist to check such behavior.

      Why I care?

      I wanted to serialize Date objects as number of seconds since epoch (because that's how they expect it on server API). Normally, I would set a global replacer function in my HTTP request sending flow:

      function objectToApiJsonReplacer(k /*string*/, v /*any*/) {
          if (this[k] instanceof Date) {
              return dateToApiFormat(this[k]);
          }
          return v;
      }
      
      function dateToApiFormat(date /*Date*/) {
          return Math.floor(date.getTime() / 1000.0);
      }
      
      JSON.stringify(body, objectToApiJsonReplacer)
      

      It works in browsers and nodejs CLI, but fails miserably in Qt.

      Attachments

        For Gerrit Dashboard: QTBUG-95324
        # Subject Branch Project Status CR V

        Activity

          People

            ratijas ivan tkachenko
            ratijas ivan tkachenko
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes