2 Copyright 2013 Daniel Wirtz <dcode@dcode.io>
\r
4 Licensed under the Apache License, Version 2.0 (the "License");
\r
5 you may not use this file except in compliance with the License.
\r
6 You may obtain a copy of the License at
\r
8 http://www.apache.org/licenses/LICENSE-2.0
\r
10 Unless required by applicable law or agreed to in writing, software
\r
11 distributed under the License is distributed on an "AS IS" BASIS,
\r
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
\r
13 See the License for the specific language governing permissions and
\r
14 limitations under the License.
\r
16 var description = "Plain JSON descriptor";
\r
18 var ProtoBuf = require(__dirname+"/../../../index.js"),
\r
19 util = require("../util.js");
\r
22 * pbjs target: Plain JSON descriptor
\r
23 * @exports pbjs/targets/json
\r
25 * @param {!ProtoBuf.Builder} builder Builder
\r
26 * @param {!Object.<string,*>=} options Options
\r
29 var json = module.exports = function(builder, options) {
\r
30 options = options || {};
\r
31 builder.resolveAll();
\r
33 // Set the pointer to the lowest common namespace (with options)
\r
34 var ptr = builder.ns;
\r
35 while (ptr.children.length === 1 && Object.keys(ptr.options).length === 0 && ptr.children[0].className === "Namespace")
\r
36 ptr = ptr.children[0];
\r
38 // Start by building the package namespace
\r
39 var pkg = ptr.fqn().substring(1),
\r
41 "package": pkg !== "" ? pkg : null
\r
43 buildNamespace(ptr, out);
\r
44 return JSON.stringify(out, null, options.min ? 0 : 4);
\r
48 * Module description.
\r
51 json.description = description;
\r
54 * Builds all structures in a namespace.
\r
55 * @param {!ProtoBuf.Reflect.Namespace} ns Namespace to build
\r
56 * @param {!Object.<string,*>} out Extended output object
\r
58 function buildNamespace(ns, out) {
\r
59 var messages, enums, services;
\r
61 "syntax" : ns.syntax || 'proto2',
\r
62 "options" : out.options || {},
\r
63 "messages" : messages = [],
\r
64 "enums" : enums = [],
\r
65 "services" : services = []
\r
67 if (!(ns instanceof ProtoBuf.Reflect.Message))
\r
68 out['isNamespace'] = true;
\r
69 util.extend(out["options"], buildOptions(ns.options));
\r
70 ns.getChildren(ProtoBuf.Reflect.Enum).forEach(function(enm) {
\r
71 enums.push(buildEnum(enm));
\r
73 if (enums.length === 0)
\r
74 delete out["enums"];
\r
75 ns.getChildren(ProtoBuf.Reflect.Message).forEach(function(msg) {
\r
76 messages.push(buildMessage(msg));
\r
78 ns.getChildren(ProtoBuf.Reflect.Service).forEach(function(svc) {
\r
79 services.push(buildService(svc));
\r
81 if (services.length === 0)
\r
82 delete out["services"];
\r
83 Array.prototype.push.apply(messages, buildExtensions(ns));
\r
84 ns.getChildren(ProtoBuf.Reflect.Namespace).forEach(function(innerNs) {
\r
85 if (innerNs.className !== "Namespace")
\r
87 var emptyMessage = {
\r
88 "name": innerNs.name,
\r
91 buildNamespace(innerNs, emptyMessage);
\r
92 messages.push(emptyMessage);
\r
94 if (messages.length === 0)
\r
95 delete out["messages"];
\r
96 if (Object.keys(out["options"]).length === 0)
\r
97 delete out["options"];
\r
101 * Builds extensions declared in the specified namespace.
\r
102 * @param {!ProtoBuf.Reflect.Namespace} ns Namespace
\r
103 * @returns {!Array.<!*>}
\r
105 function buildExtensions(ns) {
\r
106 var exts = util.groupExtensions(ns);
\r
110 Object.keys(exts).forEach(function(extFqn) {
\r
111 var extMsg = ns.resolve(extFqn),
\r
112 extFields = exts[extFqn];
\r
113 var fields, ext = {
\r
114 "ref" : ns.qn(extMsg),
\r
115 "fields" : fields = []
\r
117 extFields.forEach(function(extField) {
\r
118 fields.push(buildMessageField(extField));
\r
120 messages.push(ext);
\r
126 * Builds block-level options.
\r
127 * @param {!Object.<string,*>} options Options
\r
128 * @returns {!Object.<string,*>}
\r
130 function buildOptions(options) {
\r
131 Object.keys(options = options || {}).forEach(function(key) {
\r
132 var val = options[key];
\r
133 switch (typeof val) {
\r
140 throw Error("Illegal option type: "+typeof(val));
\r
147 * Builds a message.
\r
148 * @param {!ProtoBuf.Reflect.Message} msg Message
\r
151 function buildMessage(msg) {
\r
152 var fields, oneofs;
\r
155 "syntax" : msg.syntax || 'proto2',
\r
157 "fields" : fields = [],
\r
158 "oneofs" : oneofs = {}
\r
160 msg.getChildren(ProtoBuf.Reflect.Message.Field).forEach(function(fld) {
\r
161 if (fld instanceof ProtoBuf.Reflect.Message.ExtensionField)
\r
163 fields.push(buildMessageField(fld));
\r
165 msg.getChildren(ProtoBuf.Reflect.Message.OneOf).forEach(function(oneof) {
\r
166 oneofs[oneof.name] = buildMessageOneof(oneof);
\r
168 if (msg.extensions)
\r
169 out["extensions"] = msg.extensions;
\r
170 if (Object.keys(oneofs).length === 0)
\r
171 delete out["oneofs"];
\r
172 buildNamespace(msg, out);
\r
177 * Builds a message field.
\r
178 * @param {!ProtoBuf.Reflect.Message.Field} fld Message field
\r
181 function buildMessageField(fld) {
\r
183 "rule" : fld.map ? "map" : (fld.repeated ? "repeated" : (fld.required ? "required" : "optional")),
\r
184 "type" : fld.resolvedType ? fld.parent.qn(fld.resolvedType) : fld.type['name'],
\r
185 "keytype" : (typeof(fld.keyType) === 'string') ? fld.keyType : (fld.keyType !== null ? fld.keyType.name : undefined),
\r
186 "name" : fld instanceof ProtoBuf.Reflect.Message.ExtensionField ? fld.name.substring(fld.name.lastIndexOf(".")+1): fld.name,
\r
188 "options" : Object.keys(fld.options).length > 0 ? buildOptions(fld.options) : undefined,
\r
189 "oneof" : fld.oneof ? fld.oneof.name : undefined
\r
194 * Builds a message oneof.
\r
195 * @param {!ProtoBuf.Reflect.message.OneOf} oneof Message oneof
\r
196 * @returns {!Array.<!*>}
\r
198 function buildMessageOneof(oneof) {
\r
200 oneof.fields.forEach(function(fld) {
\r
208 * @param {!ProtoBuf.Reflect.Enum} enm Enum
\r
211 function buildEnum(enm) {
\r
215 "syntax" : enm.syntax || 'proto2',
\r
216 "values" : values = []
\r
218 enm.getChildren(ProtoBuf.Reflect.Enum.Value).forEach(function(val) {
\r
219 values.push(buildEnumValue(val));
\r
221 if (Object.keys(enm.options).length > 0)
\r
222 out["options"] = buildOptions(enm.options);
\r
227 * Builds an enum value.
\r
228 * @param {!ProtoBuf.Reflect.Enum.Value} val Enum value
\r
231 function buildEnumValue(val) {
\r
239 * Builds a service.
\r
240 * @param {!ProtoBuf.Reflect.Service} svc Service
\r
243 function buildService(svc) {
\r
247 "options": buildOptions(svc.options),
\r
250 svc.getChildren(ProtoBuf.Reflect.Service.RPCMethod).forEach(function(mtd) {
\r
252 "request": svc.qn(mtd.resolvedRequestType),
\r
253 "request_stream": mtd.requestStream,
\r
254 "response": svc.qn(mtd.resolvedResponseType),
\r
255 "response_stream": mtd.responseStream,
\r
256 "options": buildOptions(mtd.options)
\r