2008.01.29

Trimming values from JSON objects

Kategori: JSON, Programmering — Michael Schøler, Kl. 22:37:09

My current work is really focused on Ajax and JSON, and I get a lot of different things done that might be of use to others.

Today I’ve come up with a neat little function for trimming a JSON object given an array of all values to trim out. The trim function recursively runs though the JSON object and deletes all occurences of the specified values. Optionally, any present or resulting empty objects within the provided JSON object can also be deleted in the process.

My function has this form:

function jsonTrim( json, trimValuesAry, bDeleteEmptyObjects )

The first parameter json is the JSON object to trim, and also the resulting object.

The second parameter trimValuesAry is an array of values to trim out, e.g. [ "", null ]. Do note that objects are not treated by jsonTrim as values but as begin part of the data-structure. Therefore you can only specify leaf-values in trimValuesAry that can occur within objects as key/value pairs.

Finally bDeleteEmptyObjects is an optional bool parameter, it may be omitted. The default value if omitted is false. If set to true any present or resulting empty objects are also deleted.

Trimming json = { obj: { string: “foo” }, bar: 42, nil: null } with [ "foo", null ] and requesting empty objects to be deleted would result in json = { bar: 42 }:

Download (right-click and choose “Save as…”)
jsonTrim.js version 0.1.
jsonTrim-jsmin.js version 0.1 (JSMinified).
jsonTrim-v0.1.zip version 0.1 (zip archive containing all files incl. test).

Test (demo):
jsonTrim-Test.htm.
jsonTrim-jsmin-Test.htm.

License:
Creative Commons GNU LGPL.

Revision history:
2008-01-29, 22:37:
v0.1 first release.

2008.01.26

Converting JSON to XML and XML to JSON

Kategori: JSON, Programmering — Michael Schøler, Kl. 09:20:04

JSONConverting JSON to XML and back again is very useful e.g. for storing and retrieving web application state to a database.

Searching the web I found a quite extensive and robust library, honourably mentioned on xml.com, by Prof. Stefan Goessner to accomplish this conversion. However the code was not in compliance with our teams javascript code standards, and so I have taken the liberty to restructure Goessner’s two seperate scripts json2xml.js and xml2json.js into one selfcontaining script file and in the process I have made sure the code validates in JSLint.

Download: (right-click and choose “Save as…”)
JsonXml.js version 0.9-p5.
JsonXml-jsmin.js version 0.9-p5 (JSMinified).
JsonXml.zip version 0.9-p5 (zip archive containing all files incl. comparison demo).

Comparison with original implementation (demo):
XmlJson_Test.htm.
XmlJson_Test_jsmin.htm.

License:
Creative Commons GNU LGPL.

Revision history:
2008-01-29, 12:00:
v0.9-p5 fixes bug in v0.9: added handling of int and float values. See why this matters.
Transforming { pos:1, neg:-1, float:3.14 } to XML and back resulted in
{ pos:”1″, neg:”-1″, float:”3.14″ }.

2008-01-28, 16:15:
v0.9-p4 fixes bug in v0.9: added handling of empty JSON strings. See why this matters.
Transforming { string:”" } to XML and back resulted in { string: null }.
2008-01-28, 15:22:
v0.9-p3 fixes bug in v0.9: added handling of empty JSON arrays. See why this matters.
Transforming { ary:[] } to XML and back resulted in { ary: null }.
2008-01-28, 13:34:
v0.9-p2 fixes bug in v0.9-p1: #text nodes were not copied correctly.
Transforming <xml>text</xml> to JSON and back resulted in <xml></xml>.
2008-01-26, 09:20:
v0.9-p1 first release of the restructured code.

2008.01.15

JSON diffing

Kategori: JSON, Programmering — Michael Schøler, Kl. 21:02:12

I have now created a method for returning structural differences between two JSON objects. This completes my work with making a JSON merge and JSON diff implementation (although it will most certainly undergo future revisions and quirk resolving changes).

Why? Say for instance you have two JSON structures, json1 and json2. The object json1 holds an original set of data, whereas json2 represents an updated edition of json1. With the diff method you can programatically extract the differences between the two. This could e.g. be used to further limit the amount of data transmitted between the client/server (e.g. with ajax requests), without the need for specialized client side code tracking data changes. When you need to transmit the changes you simply diff the latest set received with the current.

Read my earlier article regarding JSON merging here.

Both the merge and diff methods I have created, can operate on cyclic (self-referencing) JSON structures.

Updated: Now correctly handles arrays. Please note that the ordering of items in the arrays are considered application critical. Thus, the array [1,2] is not considered similar to [2,1].

The diff and merge implementations require the Array.indexOf, Object.isArray and Object.keys methods from the prototype framework.

Further information and demos are available here:
jsonDiff and jsonMerge.

Here is the new implementation with the diff and merge methods (validates in JSLint):

  1. // Author: Michael Schøler, 2008
  2. // LGPL license, use as you like, don’t hold me responsible for success or failure though
  3. Array.prototype.compareTo = function(compareAry) {
  4.   if (this.length === compareAry.length) {
  5.     var i;
  6.     for (i = 0; i < compareAry.length; i+=1) {
  7.       if (Object.isArray(this[i]) === true) {
  8.         if (this[i].compareTo(compareAry[i]) === false) {
  9.           return false;
  10.         }
  11.         continue;
  12.       }
  13.       else if (this[i] !== compareAry[i]) {
  14.         return false;
  15.       }
  16.     }
  17.     return true;
  18.   }
  19.   return false;
  20. };
  21. var jsonDataHandler = {
  22.   merge: function(j1, j2) {
  23.     if (typeof this.merging === “undefined” || this.merging === 0) {
  24.       this.mergeCyclicCheck = [];
  25.       this.merging = 0;
  26.     }
  27.     this.merging += 1;
  28.     if (typeof j1 === “undefined”) {
  29.       j1 = {};
  30.     }
  31.     if (typeof j2 === “undefined”) {
  32.       j2 = {};
  33.     }
  34.     if (typeof this.mergeCyclicCheck === “undefined”) {
  35.       this.mergeCyclicCheck = [];
  36.     }
  37.     var key;
  38.     for (key in j2) if (j2.hasOwnProperty(key)) {
  39.       if (typeof j1[key] === “undefined”) {
  40.         j1[key] = j2[key];
  41.       }
  42.       else {
  43.         if (typeof j2[key] === “object”) {
  44.           if (this.mergeCyclicCheck.indexOf(j1[key]) >= 0) {
  45.             break;
  46.           }
  47.           this.merge(j1[key], j2[key]);
  48.           this.mergeCyclicCheck.push(j1[key]);
  49.         }
  50.         else {
  51.           j1[key] = j2[key];
  52.         }
  53.       }
  54.     }
  55.     this.merging -= 1;
  56.   },
  57.   diff: function(j1, j2) {
  58.     if (typeof this.diffing === “undefined” || this.diffing === 0) {
  59.       this.diffCyclicCheck = [];
  60.       this.diffing = 0;
  61.     }
  62.     var diffRes = {};
  63.     this.diffing += 1;
  64.     if (typeof j1 === “undefined”) {
  65.       j1 = {};
  66.     }
  67.     if (typeof j2 === “undefined”) {
  68.       j2 = {};
  69.     }
  70.     if (typeof this.diffCyclicCheck === “undefined”) {
  71.       this.diffCyclicCheck = [];
  72.     }
  73.     var key, bDiff;
  74.     for (key in j2) if (j2.hasOwnProperty(key)) { 
  75.       bDiff = false;
  76.       if (typeof j1[key] === “undefined” || typeof j1[key] != typeof j2[key]) {
  77.         bDiff = true;
  78.       }
  79.       else if (j1[key] !== j2[key]) {
  80.         if (typeof j2[key] === “object”) {
  81.           if (this.diffCyclicCheck.indexOf(j2[key]) >= 0) {
  82.             break;
  83.           }
  84.           else if (Object.isArray(j2[key])) {
  85.             if (j1[key].length !== j2[key].length || j1[key] !== j2[key]) {
  86.               if (j2[key].compareTo(j1[key]) === false) {
  87.                 bDiff = true;
  88.               }
  89.             }
  90.           }
  91.           else if (typeof j1[key] === “object”) {
  92.             var dR = this.diff(j1[key], j2[key]);
  93.             if (Object.keys(dR).length > 0) {
  94.               diffRes[key] = dR;
  95.             }
  96.           }
  97.           else {
  98.             bDiff = true;
  99.           }
  100.           this.diffCyclicCheck.push(j2[key]);
  101.         }
  102.         else if (j1[key] !== j2[key]) {
  103.           bDiff = true;
  104.         }
  105.       }
  106.       if (bDiff) {
  107.         diffRes[key] = j2[key];
  108.       }
  109.     }
  110.     for (key in j1) if (j1.hasOwnProperty(key)) {
  111.       bDiff = false;
  112.       if (typeof j2[key] === “undefined”) {
  113.         diffRes[key] = j1[key];
  114.       }
  115.     }
  116.     this.diffing -= 1;
  117.     return diffRes;
  118.   }
  119. };

You are free to download jsonDataHandler.zip which is a zip archive of the code in plain javascript and in JSMin minified format. The code is LGPL licensed (read more).

Enjoy!

2008.01.14

Wulffmorgenthaler Facebook applikation

Kategori: Programmering — Michael Schøler, Kl. 19:26:33

Hinnerup Net ApS har idag lagt sidste hånd på en Facebook applikation som vi har lavet for Wullfmorgenthaler ApS. Og den må du vist liiiiiige se at få tilføjet til din Facebook profil i en fart, der er tale om welt-klasse her jo! Get going, installer applikationen med det samme!