4

I've been looking around for a way to do this but can't seem to find anything, I have different configuration objects that I need to save as a text in variables for some processing later on, here is a sample:

object:

args.config.config = {
        next: null,
        final:[],
        delimiter: '~', header: false,
        step: function (row) {
            var item = {
                'line_code': row.data[0][0],
                'order': row.data[0][1]
            }
            args.config.config.final.push(item);
        },
        complete: function (result) {
            console.log('Reading data completed. Processing.');
            return args.config.config.next(null, args.config.config.final);
        },
        error: function () {
            console.log('There was an error parsing');
        }'
    }

I need to save this as a string, so something like:

args.config.config = "{object goes here}";

Without putting everything on one giant line or adding break line characters as this will be parsed later to be used in a config, and that will mess things up, any ideas?

UPDATE: So changing them into text may not be the best solution, these configs will be stored in a mongo database, so it may take them as is (I have not tried it yet).

One of the other problems I was running into was that in the config object I had this:

final.push(item)

and

return next(null, final)

Which will be defined in another file using the config object:

other file:

exports.parse = function(args, next){//next is what I need to call in the config

    var final = []; //this is the final referred to in the config object
    ....
    Baby.parse(data, args.config)
}

So the return next(null, final) and final.push(result) have to refer the the var / function in the new file, but I have no idea how to get that to work, that't why I had to add a final array in the config object and a null next function, then assign it like so:

exports.parse = function(args, next){
    args.config.next = next;
    ....
    Baby.parse(data, args.config)
}

the object was calling it with the ugly line:

   return args.config.config.next(null, args.config.config.final);

If anyone has a way around this, it would be much appreciated.

Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
Mankind1023
  • 7,198
  • 16
  • 56
  • 86
  • Why do the objects need to be text in order to be stored for later? – Scott Marcus Nov 29 '16 at 20:59
  • You can't because of the functions... Can you say the strings/numbers in another object and have the function use those values? – epascarello Nov 29 '16 at 21:01
  • The term for what you want to do is "serialize". There are entire libraries devoted to serializing and deserializing objects with their methods. The most common approach is to define the object as an instance of a class, store the class name as part of the serialization, and then on deserialization reconstitute an instance of the class, possibly using the notion of a "class factory" which can instantiate an object based on the class name, along with its methods, from the data. –  Nov 29 '16 at 21:06
  • you have a single comma `'` after a close curly bracket at the end. I suppose it's a typo – Paolo Nov 29 '16 at 21:14
  • Is there a way to get over the args.config.config.final.push(item) with this? – Mankind1023 Nov 30 '16 at 18:18

1 Answers1

4

If you use JSON.stringify with a "replacer" function and JSON.parse with a "reviver" function along with new Function(), you can do it:

I'm not sure I'm following the second (updated) question you have. Once the object is parsed back into an object, why can't you just initialize the next and final properties to valid objects before calling any of the object's methods? You can even add tests into that method that checks for the existence of final and next before returning anything.

var myObj = {
        next: null,
        final:[],
        delimiter: '~', 
        header: false,
        step: function (row) {
            var item = {
                'line_code': row.data[0][0],
                'order': row.data[0][1]
            };
            args.config.config.final.push(item);
        },
        complete: function (result) {
            console.log('Reading data completed. Processing.');
            return args.config.config.next(null, args.config.config.final);
        },
        error: function () {
            console.log('There was an error parsing');
        }
    };

// Stringify the object using a replacer function that will explicitly
// turn functions into strings
var myObjString = JSON.stringify(myObj, function(key, val) {
        return (typeof val === 'function') ? '' + val : val;
});

// Now, parse back into an object with a reviver function to
// test for function values and create new functions from them:
var obj = JSON.parse(myObjString, function(key, val){
  
    // Make sure the current value is not null (is a string)
    // and that the first characters are "function"
    if(typeof val === "string" && val.indexOf('function') === 0){

      // Isolate the argument names list
      var start = val.indexOf("(") + 1;
      var end = val.indexOf(")");     
      var argListString = val.substring(start,end).split(",");
      
      // Isolate the body of the function
      var body = val.substr(val.indexOf("{"), val.length - end + 1);
      
      // Construct a new function using the argument names and body
      // stored in the string:
      return new Function(argListString, body);
      
    } else {
      // Non-function property, just return the value
      return val;
    } 
  }
);

// Test the method:
obj.error(); // 'There was an error parsing' is written to console.

// Examine the object:
console.log(obj);
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71