Bug 727967 - Support conversion from/to JSON in Dict.jsm. r=gavin
authorAbhishek Potnis <abhishekp.bugzilla@gmail.com>
Wed, 10 Oct 2012 21:55:38 +0530
changeset 111019 c0977a9122d194de39414881c61e70ec12c06b8e
parent 111018 1c4ecfb93f84671095ad3e0acb9044a2c5d88389
child 111020 a79caf5f26b3b3f243e39b59942690d6d4a48b1b
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersgavin
bugs727967
milestone19.0a1
Bug 727967 - Support conversion from/to JSON in Dict.jsm. r=gavin
toolkit/content/Dict.jsm
toolkit/content/tests/unit/test_dict.js
--- a/toolkit/content/Dict.jsm
+++ b/toolkit/content/Dict.jsm
@@ -24,20 +24,23 @@ function unconvert(aProp) {
 /**
  * A dictionary of strings to arbitrary JS objects. This should be used whenever
  * the keys are potentially arbitrary, to avoid collisions with built-in
  * properties.
  *
  * @param aInitial An object containing the initial keys and values of this
  *                 dictionary. Only the "own" enumerable properties of the
  *                 object are considered.
+ *                 If |aInitial| is a string, it is assumed to be JSON and parsed into an object.
  */
 function Dict(aInitial) {
   if (aInitial === undefined)
     aInitial = {};
+  if (typeof aInitial == "string")
+    aInitial = JSON.parse(aInitial);
   var items = {}, count = 0;
   // That we don't look up the prototype chain is guaranteed by Iterator.
   for (var [key, val] in Iterator(aInitial)) {
     items[convert(key)] = val;
     count++;
   }
   this._state = {count: count, items: items};
   return Object.freeze(this);
@@ -220,16 +223,27 @@ Dict.prototype = Object.freeze({
   get items() {
     // If we don't capture this._state.items here then the this-binding will be
     // incorrect when the generator is executed
     var items = this._state.items;
     return ([unconvert(k), items[k]] for (k in items));
   },
 
   /**
-   * Returns a string representation of this dictionary.
+   * Returns a String representation of this dictionary.
    */
   toString: function Dict_toString() {
     return "{" +
       [(key + ": " + val) for ([key, val] in this.items)].join(", ") +
       "}";
   },
+
+  /**
+   * Returns a JSON representation of this dictionary.
+   */
+  toJSON: function Dict_toJSON() {
+    let obj = {};
+    for (let [key, item] of Iterator(this._state.items)) {
+      obj[unconvert(key)] = item;
+    }
+    return JSON.stringify(obj);
+  },
 });
--- a/toolkit/content/tests/unit/test_dict.js
+++ b/toolkit/content/tests/unit/test_dict.js
@@ -247,25 +247,58 @@ function test_set_property_lazy_getter()
 
     thunkCalled = false;
     do_check_false(dict.isLazyGetter("foo"));
     do_check_eq(dict.get("foo"), "bar");
     do_check_false(thunkCalled);
   }
 }
 
+// This is used by both test_construct_dict_from_json_string and test_serialize_dict_to_json_string
+function _sort_comp_arr(arr1,arr2){
+  arr1.sort();
+  arr2.sort();
+  do_check_eq(arr1.toString(),arr2.toString());
+}
+
+/**
+ * Tests constructing a dictionary from a JSON string.
+ */
+function test_construct_dict_from_json_string() {
+  let d1 = new Dict({a:1, b:2, c:"foobar"});
+  let d2 = new Dict(JSON.stringify(({a:1, b:2, c:"foobar"})));
+  _sort_comp_arr(d1.listkeys(),d2.listkeys());
+  do_check_eq(d1.get("a"), d2.get("a"));
+  do_check_eq(d1.get("b"), d2.get("b"));
+  do_check_eq(d1.get("c"), d2.get("c"));
+}
+
+/**
+ * Tests serializing a dictionary to a JSON string.
+ */
+function test_serialize_dict_to_json_string() {
+  let d1 = new Dict({a:1, b:2, c:"foobar"});
+  let d2 = new Dict(d1.toJSON());
+  _sort_comp_arr(d1.listkeys(),d2.listkeys());
+  do_check_eq(d1.get("a"), d2.get("a"));
+  do_check_eq(d1.get("b"), d2.get("b"));
+  do_check_eq(d1.get("c"), d2.get("c"));
+}
+
 var tests = [
   test_get_set_has_del,
   test_get_default,
   test_collisions_with_builtins,
   test_count,
   test_copy,
   test_listers,
   test_iterators,
   test_set_property_strict,
   test_set_property_non_strict,
-  test_set_property_lazy_getter
+  test_set_property_lazy_getter,
+  test_construct_dict_from_json_string,
+  test_serialize_dict_to_json_string
 ];
 
 function run_test() {
   for (let [, test] in Iterator(tests))
     test();
 }