diff --git a/modules/ve2/dm/ve.dm.HTMLConverter.js b/modules/ve2/dm/ve.dm.HTMLConverter.js
index 112d6d8766..12d0f0dac2 100644
--- a/modules/ve2/dm/ve.dm.HTMLConverter.js
+++ b/modules/ve2/dm/ve.dm.HTMLConverter.js
@@ -199,7 +199,7 @@ ve.dm.HTMLConverter.generateAnnotatedContent = function( content, annotations )
if ( annotations[i].data !== undefined && Object.keys(annotations[i].data).length === 0 ) {
delete annotations[i].data;
}
- annoationMap[JSON.stringify( annotations[i] )] = annotations[i];
+ annoationMap[ve.getHash( annotations[i] )] = annotations[i];
}
for ( i = 0; i < characters.length; i++ ) {
characters[i] = [characters[i], annoationMap];
diff --git a/modules/ve2/ve.js b/modules/ve2/ve.js
index beef0779dd..57e79b476b 100644
--- a/modules/ve2/ve.js
+++ b/modules/ve2/ve.js
@@ -68,12 +68,16 @@ ve.inArray = $.inArray;
*
* This is actually an alias for jQuery.json, which falls back to window.JSON if present.
*
+ * WARNING: 2 objects can have the same contents but not the same hash if the properties were set
+ * in a different order. Recursive sorting may nessecary prior to hashing, or a hashing algorithm
+ * that produces order-safe reults may need to be used here instead.
+ *
* @static
* @method
* @param {Object} obj Object to generate hash for
* @returns {String} Hash of object
*/
-ve.getHash = $.toJson;
+ve.getHash = $.toJSON;
/**
* Gets an array of all property names in an object.