0

I've come up with the following function for converting a multiline, nicely indented json to a single line

function(text) {
    var outerRX = /((?:".*?")|(\s|\n|\r)+)/g,
        innerRX = /^(\s|\n|\r)+$/;

    return text.replace(outerRX, function($0, $1) {
        return $1.match(innerRX) ? "" : $1 ;
    });
}

Can anyone come up with something better, both in terms of efficiency and fixing bugs that exist in my implementation (e.g. mine breaks when parsing

{
    "property":"is dangerously
             spaced out" 
}

or

{
    "property":"is dangerously \" punctuated" 
}
5
  • Are you attempting to minify the JSON? There are open source solutions that exist for this. Commented Apr 26, 2011 at 13:54
  • Ideally, yes, it would be minified server side, but no-one here has the time to do that right now, so I have to have an easily maintainable (i.e. indented, multiline) json file that gets passed exactly as is to jQuery.ajax Commented Apr 26, 2011 at 13:58
  • Have you looked at jsmin? There are both server side and client side versions you can use. Commented Apr 26, 2011 at 14:23
  • The trouble with jsmin is that it minifies javascript, but json is only a subset of javascript, so I bet it runs a whole load of regex that aren't needed in this case. So while it's undoubtedly less buggy than my function, it's probably less efficient than a non-buggy, single-purpose json minifying function would be. Also, I'm not sure the link you posted above for a client-side version is client-side - all I can find there are links to C and .exe files - both server side Commented Apr 26, 2011 at 14:35
  • Crack open jsmin and take what you want. Commented Apr 26, 2011 at 15:01

2 Answers 2

2

For this kind of problem, I follow the adage that adding regex just gives you two problems. It's a simple enough parsing problem, so here's a parsing solution:

var minifyJson = function (inJson) {
  var outJson, // the output string
      ch,      // the current character
      at,      // where we're at in the input string
      advance = function () {
        at += 1;
        ch = inJson.charAt(at);
      },
      skipWhite = function () {
        do { advance(); } while (ch && (ch <= ' '));
      },
      append = function () {
        outJson += ch;
      },
      copyString = function () {
        while (true) {
          advance();
          append();
          if (!ch || (ch === '"')) {
            return;
          }
          if (ch === '\\') {
            advance();
            append();
          }
        }
      },
      initialize = function () {
        outJson = "";
        at = -1;
      };

  initialize();
  skipWhite();

  while (ch) {
    append();
    if (ch === '"') {
      copyString();
    }
    skipWhite();
  }
  return outJson;
};

Note that the code does not have any error-checking to see if the JSON is properly formed. The only error (no closing quotes for a string) is ignored.

Sign up to request clarification or add additional context in comments.

1 Comment

I'm very reluctant to admit defeat using regex, but have found that javascript regex's lack of support for lookbehind is a real hindrance, so I'm going to try your approach - thanks very much for sharing it.
0

This fixes the two bugs in the question, but probably not very efficiently

function(text) {
    var outerRX = /((?:"([^"]|(\\"))*?(?!\\)")|(\s|\n|\r)+)/g,
    innerRX = /^(\s|\n|\r)+$/;

    return text.replace(outerRX, function($0, $1) {
        return $1.match(/^(\s|\n|\r)+$/) ? "" : $1 ;
    });
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.