Path: blob/trunk/third_party/closure/goog/proto2/objectserializer.js
2868 views
// Copyright 2008 The Closure Library Authors. All Rights Reserved.1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS-IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314/**15* @fileoverview Protocol Buffer 2 Serializer which serializes messages16* into anonymous, simplified JSON objects.17*18*/1920goog.provide('goog.proto2.ObjectSerializer');2122goog.require('goog.asserts');23goog.require('goog.proto2.FieldDescriptor');24goog.require('goog.proto2.Serializer');25goog.require('goog.string');26272829/**30* ObjectSerializer, a serializer which turns Messages into simplified31* ECMAScript objects.32*33* @param {goog.proto2.ObjectSerializer.KeyOption=} opt_keyOption If specified,34* which key option to use when serializing/deserializing.35* @param {boolean=} opt_serializeBooleanAsNumber If specified and true, the36* serializer will convert boolean values to 0/1 representation.37* @constructor38* @extends {goog.proto2.Serializer}39*/40goog.proto2.ObjectSerializer = function(41opt_keyOption, opt_serializeBooleanAsNumber) {42this.keyOption_ = opt_keyOption;43this.serializeBooleanAsNumber_ = opt_serializeBooleanAsNumber;44};45goog.inherits(goog.proto2.ObjectSerializer, goog.proto2.Serializer);464748/**49* An enumeration of the options for how to emit the keys in50* the generated simplified object.51*52* @enum {number}53*/54goog.proto2.ObjectSerializer.KeyOption = {55/**56* Use the tag of the field as the key (default)57*/58TAG: 0,5960/**61* Use the name of the field as the key. Unknown fields62* will still use their tags as keys.63*/64NAME: 165};666768/**69* Serializes a message to an object.70*71* @param {goog.proto2.Message} message The message to be serialized.72* @return {!Object} The serialized form of the message.73* @override74*/75goog.proto2.ObjectSerializer.prototype.serialize = function(message) {76var descriptor = message.getDescriptor();77var fields = descriptor.getFields();7879var objectValue = {};8081// Add the defined fields, recursively.82for (var i = 0; i < fields.length; i++) {83var field = fields[i];8485var key = this.keyOption_ == goog.proto2.ObjectSerializer.KeyOption.NAME ?86field.getName() :87field.getTag();888990if (message.has(field)) {91if (field.isRepeated()) {92var array = [];93objectValue[key] = array;9495for (var j = 0; j < message.countOf(field); j++) {96array.push(this.getSerializedValue(field, message.get(field, j)));97}9899} else {100objectValue[key] = this.getSerializedValue(field, message.get(field));101}102}103}104105// Add the unknown fields, if any.106message.forEachUnknown(function(tag, value) { objectValue[tag] = value; });107108return objectValue;109};110111112/** @override */113goog.proto2.ObjectSerializer.prototype.getSerializedValue = function(114field, value) {115116// Handle the case where a boolean should be serialized as 0/1.117// Some deserialization libraries, such as GWT, can use this notation.118if (this.serializeBooleanAsNumber_ &&119field.getFieldType() == goog.proto2.FieldDescriptor.FieldType.BOOL &&120goog.isBoolean(value)) {121return value ? 1 : 0;122}123124return goog.proto2.ObjectSerializer.base(125this, 'getSerializedValue', field, value);126};127128129/** @override */130goog.proto2.ObjectSerializer.prototype.getDeserializedValue = function(131field, value) {132133// Gracefully handle the case where a boolean is represented by 0/1.134// Some serialization libraries, such as GWT, can use this notation.135if (field.getFieldType() == goog.proto2.FieldDescriptor.FieldType.BOOL &&136goog.isNumber(value)) {137return Boolean(value);138}139140return goog.proto2.ObjectSerializer.base(141this, 'getDeserializedValue', field, value);142};143144145/**146* Deserializes a message from an object and places the147* data in the message.148*149* @param {goog.proto2.Message} message The message in which to150* place the information.151* @param {*} data The data of the message.152* @override153*/154goog.proto2.ObjectSerializer.prototype.deserializeTo = function(message, data) {155var descriptor = message.getDescriptor();156157for (var key in data) {158var field;159var value = data[key];160161var isNumeric = goog.string.isNumeric(key);162163if (isNumeric) {164field = descriptor.findFieldByTag(key);165} else {166// We must be in Key == NAME mode to lookup by name.167goog.asserts.assert(168this.keyOption_ == goog.proto2.ObjectSerializer.KeyOption.NAME,169'Key mode ' + this.keyOption_ + 'for key ' + key + ' is not ' +170goog.proto2.ObjectSerializer.KeyOption.NAME);171172field = descriptor.findFieldByName(key);173}174175if (field) {176if (field.isRepeated()) {177goog.asserts.assert(178goog.isArray(value),179'Value for repeated field ' + field + ' must be an array.');180181for (var j = 0; j < value.length; j++) {182message.add(field, this.getDeserializedValue(field, value[j]));183}184} else {185goog.asserts.assert(186!goog.isArray(value),187'Value for non-repeated field ' + field + ' must not be an array.');188message.set(field, this.getDeserializedValue(field, value));189}190} else {191if (isNumeric) {192// We have an unknown field.193message.setUnknown(Number(key), value);194} else {195// Named fields must be present.196goog.asserts.fail('Failed to find field: ' + key);197}198}199}200};201202203