serializer.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /**
  2. * Durandal 2.1.0 Copyright (c) 2012 Blue Spire Consulting, Inc. All Rights Reserved.
  3. * Available via the MIT license.
  4. * see: http://durandaljs.com or https://github.com/BlueSpire/Durandal for details.
  5. */
  6. /**
  7. * Serializes and deserializes data to/from JSON.
  8. * @module serializer
  9. * @requires system
  10. */
  11. define(['durandal/system'], function(system) {
  12. /**
  13. * @class SerializerModule
  14. * @static
  15. */
  16. return {
  17. /**
  18. * The name of the attribute that the serializer should use to identify an object's type.
  19. * @property {string} typeAttribute
  20. * @default type
  21. */
  22. typeAttribute: 'type',
  23. /**
  24. * The amount of space to use for indentation when writing out JSON.
  25. * @property {string|number} space
  26. * @default undefined
  27. */
  28. space:undefined,
  29. /**
  30. * The default replacer function used during serialization. By default properties starting with '_' or '$' are removed from the serialized object.
  31. * @method replacer
  32. * @param {string} key The object key to check.
  33. * @param {object} value The object value to check.
  34. * @return {object} The value to serialize.
  35. */
  36. replacer: function(key, value) {
  37. if(key){
  38. var first = key[0];
  39. if(first === '_' || first === '$'){
  40. return undefined;
  41. }
  42. }
  43. return value;
  44. },
  45. /**
  46. * Serializes the object.
  47. * @method serialize
  48. * @param {object} object The object to serialize.
  49. * @param {object} [settings] Settings can specify a replacer or space to override the serializer defaults.
  50. * @return {string} The JSON string.
  51. */
  52. serialize: function(object, settings) {
  53. settings = (settings === undefined) ? {} : settings;
  54. if(system.isString(settings) || system.isNumber(settings)) {
  55. settings = { space: settings };
  56. }
  57. return JSON.stringify(object, settings.replacer || this.replacer, settings.space || this.space);
  58. },
  59. /**
  60. * Gets the type id for an object instance, using the configured `typeAttribute`.
  61. * @method getTypeId
  62. * @param {object} object The object to serialize.
  63. * @return {string} The type.
  64. */
  65. getTypeId: function(object) {
  66. if (object) {
  67. return object[this.typeAttribute];
  68. }
  69. return undefined;
  70. },
  71. /**
  72. * Maps type ids to object constructor functions. Keys are type ids and values are functions.
  73. * @property {object} typeMap.
  74. */
  75. typeMap: {},
  76. /**
  77. * Adds a type id/constructor function mampping to the `typeMap`.
  78. * @method registerType
  79. * @param {string} typeId The type id.
  80. * @param {function} constructor The constructor.
  81. */
  82. registerType: function() {
  83. var first = arguments[0];
  84. if (arguments.length == 1) {
  85. var id = first[this.typeAttribute] || system.getModuleId(first);
  86. this.typeMap[id] = first;
  87. } else {
  88. this.typeMap[first] = arguments[1];
  89. }
  90. },
  91. /**
  92. * The default reviver function used during deserialization. By default is detects type properties on objects and uses them to re-construct the correct object using the provided constructor mapping.
  93. * @method reviver
  94. * @param {string} key The attribute key.
  95. * @param {object} value The object value associated with the key.
  96. * @param {function} getTypeId A custom function used to get the type id from a value.
  97. * @param {object} getConstructor A custom function used to get the constructor function associated with a type id.
  98. * @return {object} The value.
  99. */
  100. reviver: function(key, value, getTypeId, getConstructor) {
  101. var typeId = getTypeId(value);
  102. if (typeId) {
  103. var ctor = getConstructor(typeId);
  104. if (ctor) {
  105. if (ctor.fromJSON) {
  106. return ctor.fromJSON(value);
  107. }
  108. return new ctor(value);
  109. }
  110. }
  111. return value;
  112. },
  113. /**
  114. * Deserialize the JSON.
  115. * @method deserialize
  116. * @param {string} text The JSON string.
  117. * @param {object} [settings] Settings can specify a reviver, getTypeId function or getConstructor function.
  118. * @return {object} The deserialized object.
  119. */
  120. deserialize: function(text, settings) {
  121. var that = this;
  122. settings = settings || {};
  123. var getTypeId = settings.getTypeId || function(object) { return that.getTypeId(object); };
  124. var getConstructor = settings.getConstructor || function(id) { return that.typeMap[id]; };
  125. var reviver = settings.reviver || function(key, value) { return that.reviver(key, value, getTypeId, getConstructor); };
  126. return JSON.parse(text, reviver);
  127. },
  128. /**
  129. * Clone the object.
  130. * @method clone
  131. * @param {object} obj The object to clone.
  132. * @param {object} [settings] Settings can specify any of the options allowed by the serialize or deserialize methods.
  133. * @return {object} The new clone.
  134. */
  135. clone:function(obj, settings) {
  136. return this.deserialize(this.serialize(obj, settings), settings);
  137. }
  138. };
  139. });