智慧水务管理系统 - 精河县供水工程综合管理平台

protojson.js 33KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925
  1. // Copyright 2021 Google LLC
  2. // Copyright 2026 The protobuf.js Authors
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. // Derived from proto3-json-serializer v3.0.4 and modified by The protobuf.js Authors.
  16. "use strict";
  17. var protobuf = require("../light");
  18. /* global BigInt */
  19. var Type = protobuf.Type,
  20. Enum = protobuf.Enum,
  21. util = protobuf.util;
  22. var protojson = protobuf.protojson = module.exports = {};
  23. function isExtension(field) {
  24. return Boolean(field.declaringField) || field.name.charAt(0) === ".";
  25. }
  26. function extensionName(field) {
  27. var df = field.declaringField || field,
  28. full = df.fullName.charAt(0) === "." ? df.fullName.slice(1) : df.fullName;
  29. return "[" + (df.protoName ? full.replace(/[^.]+$/, df.protoName) : full) + "]";
  30. }
  31. function indexField(index, key, field, type) {
  32. var existing = index[key];
  33. if (existing !== undefined && existing !== field)
  34. throw Error(type.fullName + ": duplicate ProtoJSON field name " + JSON.stringify(key));
  35. index[key] = field;
  36. }
  37. function fieldsByJsonName(type) {
  38. if (type._fieldsByJsonName)
  39. return type._fieldsByJsonName;
  40. var index = Object.create(null),
  41. fields = type.fieldsArray,
  42. i = 0;
  43. for (; i < fields.length; ++i) {
  44. var field = fields[i].resolve();
  45. if (isExtension(field))
  46. indexField(index, extensionName(field), field, type);
  47. else {
  48. indexField(index, field.name, field, type);
  49. indexField(index, field.jsonName, field, type);
  50. indexField(index, field.protoName, field, type);
  51. }
  52. }
  53. type._fieldsByJsonName = index;
  54. return index;
  55. }
  56. // --- reading scalars ---
  57. var INT_RANGE = {
  58. int32: ["-2147483648", "2147483647"],
  59. sint32: ["-2147483648", "2147483647"],
  60. sfixed32: ["-2147483648", "2147483647"],
  61. uint32: ["0", "4294967295"],
  62. fixed32: ["0", "4294967295"],
  63. int64: ["-9223372036854775808", "9223372036854775807"],
  64. sint64: ["-9223372036854775808", "9223372036854775807"],
  65. sfixed64: ["-9223372036854775808", "9223372036854775807"],
  66. uint64: ["0", "18446744073709551615"],
  67. fixed64: ["0", "18446744073709551615"]
  68. };
  69. var LONG_TYPE = { int64: 1, uint64: 1, sint64: 1, fixed64: 1, sfixed64: 1 };
  70. var MAX_FLOAT = 3.4028234663852886e38;
  71. var hasBigInt = typeof BigInt !== "undefined";
  72. var NUMERIC_RE = /^[+-]?(?:[0-9]*\.[0-9]+|[0-9]+\.?)(?:[eE][+-]?[0-9]+)?$/;
  73. var SKIP = {};
  74. function invalid(name, value, what) {
  75. return Error(name + ": " + what + ": " + JSON.stringify(value));
  76. }
  77. function parseIntegerString(value, type, name) {
  78. var str;
  79. if (typeof value === "number") {
  80. if (!isFinite(value) || Math.floor(value) !== value)
  81. throw invalid(name, value, "not an integer");
  82. str = numberToIntString(value);
  83. } else if (typeof value === "string") {
  84. if (value.length === 0 || /^\s|\s$/.test(value))
  85. throw invalid(name, value, "invalid integer");
  86. if (/^[+-]?[0-9]+$/.test(value))
  87. str = value;
  88. else if (NUMERIC_RE.test(value)) {
  89. var num = Number(value);
  90. if (!isFinite(num) || Math.floor(num) !== num)
  91. throw invalid(name, value, "not an integer");
  92. str = numberToIntString(num);
  93. } else
  94. throw invalid(name, value, "invalid integer");
  95. } else
  96. throw invalid(name, value, "expected integer (number or string)");
  97. var range = INT_RANGE[type];
  98. if (LONG_TYPE[type]) {
  99. if (hasBigInt) {
  100. var big = BigInt(str);
  101. if (big < BigInt(range[0]) || big > BigInt(range[1]))
  102. throw invalid(name, value, "out of range for " + type);
  103. }
  104. } else if (Number(str) < Number(range[0]) || Number(str) > Number(range[1]))
  105. throw invalid(name, value, "out of range for " + type);
  106. return str;
  107. }
  108. function parseMapIntegerKey(key, type, name) {
  109. var unsigned = type === "uint32" || type === "fixed32" || type === "uint64" || type === "fixed64";
  110. if (!(unsigned ? /^[0-9]+$/ : /^-?[0-9]+$/).test(key))
  111. throw invalid(name, key, "invalid " + type + " map key");
  112. if (hasBigInt) {
  113. var big = BigInt(key),
  114. range = INT_RANGE[type];
  115. if (big < BigInt(range[0]) || big > BigInt(range[1]))
  116. throw invalid(name, key, "out of range for " + type + " map key");
  117. return big.toString();
  118. }
  119. parseIntegerString(key, type, name);
  120. if (LONG_TYPE[type]) {
  121. var normalized = key.replace(/^-?0+(?=\d)/, key.charAt(0) === "-" ? "-" : "");
  122. return normalized === "-0" ? "0" : normalized;
  123. }
  124. return String(Number(key));
  125. }
  126. function numberToIntString(num) {
  127. if (num >= -9007199254740991 && num <= 9007199254740991)
  128. return String(num);
  129. return num.toFixed(0);
  130. }
  131. function parseFloat32Or64(value, isFloat, name) {
  132. var num;
  133. if (typeof value === "number") {
  134. if (!isFinite(value))
  135. throw invalid(name, value, "number out of range");
  136. num = value;
  137. } else if (value === "NaN")
  138. return NaN;
  139. else if (value === "Infinity")
  140. return Infinity;
  141. else if (value === "-Infinity")
  142. return -Infinity;
  143. else if (typeof value === "string") {
  144. if (value.length === 0 || /^\s|\s$/.test(value) || !NUMERIC_RE.test(value))
  145. throw invalid(name, value, "invalid number");
  146. num = Number(value);
  147. if (!isFinite(num))
  148. throw invalid(name, value, "invalid number");
  149. } else
  150. throw invalid(name, value, "expected number");
  151. if (isFloat && Math.abs(num) > MAX_FLOAT)
  152. throw invalid(name, value, "out of range for float");
  153. return num;
  154. }
  155. function validateUtf16(value, name) {
  156. for (var i = 0; i < value.length; ++i) {
  157. var c = value.charCodeAt(i);
  158. if (c >= 0xD800 && c <= 0xDBFF) {
  159. var next = value.charCodeAt(i + 1);
  160. if (!(next >= 0xDC00 && next <= 0xDFFF))
  161. throw invalid(name, value, "unpaired high surrogate");
  162. ++i;
  163. } else if (c >= 0xDC00 && c <= 0xDFFF)
  164. throw invalid(name, value, "unpaired low surrogate");
  165. }
  166. }
  167. function parseBytes(value, name) {
  168. if (typeof value !== "string")
  169. throw invalid(name, value, "expected base64 string");
  170. var s = value.replace(/-/g, "+").replace(/_/g, "/");
  171. while (s.length % 4)
  172. s += "=";
  173. var buffer = util.newBuffer(util.base64.length(s));
  174. util.base64.decode(s, buffer, 0);
  175. return buffer;
  176. }
  177. function longFromString(str, unsigned) {
  178. return util.Long ? util.Long.fromString(str, unsigned) : parseInt(str, 10);
  179. }
  180. function readScalar(type, value, name) {
  181. switch (type) {
  182. case "int32": case "sint32": case "sfixed32":
  183. case "uint32": case "fixed32":
  184. return Number(parseIntegerString(value, type, name));
  185. case "int64": case "sint64": case "sfixed64":
  186. return longFromString(parseIntegerString(value, type, name), false);
  187. case "uint64": case "fixed64":
  188. return longFromString(parseIntegerString(value, type, name), true);
  189. case "float":
  190. return parseFloat32Or64(value, true, name);
  191. case "double":
  192. return parseFloat32Or64(value, false, name);
  193. case "bool":
  194. if (typeof value !== "boolean")
  195. throw invalid(name, value, "expected boolean");
  196. return value;
  197. case "string":
  198. if (typeof value !== "string")
  199. throw invalid(name, value, "expected string");
  200. validateUtf16(value, name);
  201. return value;
  202. case "bytes":
  203. return parseBytes(value, name);
  204. default:
  205. throw Error(name + ": unsupported scalar type " + type);
  206. }
  207. }
  208. function readEnum(enm, value, name, options) {
  209. if (typeof value === "string") {
  210. var num = enm.values[value];
  211. if (num !== undefined)
  212. return num;
  213. if (options.ignoreUnknownFields)
  214. return SKIP;
  215. throw invalid(name, value, "unknown enum value");
  216. }
  217. if (typeof value === "number") {
  218. if (!isFinite(value) || Math.floor(value) !== value)
  219. throw invalid(name, value, "invalid enum number");
  220. return value;
  221. }
  222. if (value === null && enm.fullName === ".google.protobuf.NullValue")
  223. return 0;
  224. throw invalid(name, value, "expected enum string or number");
  225. }
  226. function readMapKey(field, key) {
  227. switch (field.keyType) {
  228. case "bool":
  229. if (key !== "true" && key !== "false")
  230. throw invalid(field.fullName, key, "invalid bool map key");
  231. return key;
  232. case "string":
  233. validateUtf16(key, field.fullName);
  234. return key;
  235. case "int32": case "sint32": case "sfixed32":
  236. case "uint32": case "fixed32":
  237. case "int64": case "sint64": case "sfixed64":
  238. case "uint64": case "fixed64":
  239. return parseMapIntegerKey(key, field.keyType, field.fullName);
  240. default:
  241. throw Error(field.fullName + ": unsupported map key type " + field.keyType);
  242. }
  243. }
  244. // --- reading messages ---
  245. function readField(field, value, options, depth) {
  246. if (field.map) {
  247. if (value === null || typeof value !== "object" || Array.isArray(value))
  248. throw invalid(field.fullName, value, "expected object for map");
  249. var map = Object.create(null), k;
  250. for (k in value)
  251. if (hasOwn(value, k)) {
  252. var mk = readMapKey(field, k),
  253. mv = readSingular(field, value[k], options, depth);
  254. if (mv !== SKIP) {
  255. if (hasOwn(map, mk))
  256. throw invalid(field.fullName, k, "duplicate map key");
  257. map[mk] = mv;
  258. }
  259. }
  260. return map;
  261. }
  262. if (field.repeated) {
  263. if (!Array.isArray(value))
  264. throw invalid(field.fullName, value, "expected array");
  265. var arr = [], i = 0;
  266. for (; i < value.length; ++i) {
  267. if (value[i] === null && !isValueType(field.resolvedType))
  268. throw invalid(field.fullName, null, "null element");
  269. var el = readSingular(field, value[i], options, depth);
  270. if (el !== SKIP)
  271. arr.push(el);
  272. }
  273. return arr;
  274. }
  275. return readSingular(field, value, options, depth);
  276. }
  277. function readSingular(field, value, options, depth) {
  278. if (field.resolvedType instanceof Type)
  279. return readMessage(field.resolvedType, value, options, depth + 1);
  280. if (field.resolvedType instanceof Enum)
  281. return readEnum(field.resolvedType, value, field.fullName, options);
  282. return readScalar(field.type, value, field.fullName);
  283. }
  284. function isValueType(type) {
  285. return type instanceof Type && type.fullName === ".google.protobuf.Value";
  286. }
  287. function isImplicitDefault(field, value) {
  288. if (field.hasPresence || field.repeated || field.map || field.resolvedType instanceof Type)
  289. return false;
  290. if (field.resolvedType instanceof Enum)
  291. return value === 0;
  292. switch (field.type) {
  293. case "bool": return value === false;
  294. case "string": return value === "";
  295. case "bytes": return value == null || value.length === 0;
  296. default: return longToNumber(value) === 0;
  297. }
  298. }
  299. function readMessage(type, value, options, depth) {
  300. if (depth > util.recursionLimit)
  301. throw Error("max depth exceeded");
  302. var wkt = WKT_FROM[type.fullName];
  303. if (wkt)
  304. return wkt(type, value, options, depth);
  305. if (value === null || typeof value !== "object" || Array.isArray(value))
  306. throw invalid(type.fullName, value, "expected object");
  307. var index = fieldsByJsonName(type),
  308. out = {},
  309. seenFields = Object.create(null),
  310. seenOneofs = Object.create(null),
  311. key;
  312. for (key in value) {
  313. if (!hasOwn(value, key))
  314. continue;
  315. var field = index[key];
  316. if (field === undefined) {
  317. if (options.ignoreUnknownFields)
  318. continue;
  319. throw invalid(type.fullName, key, "unknown field");
  320. }
  321. if (seenFields[field.name])
  322. throw invalid(type.fullName, key, "duplicate field");
  323. seenFields[field.name] = true;
  324. var fv = value[key], fieldValue;
  325. if (fv === null) {
  326. if (isValueType(field.resolvedType))
  327. fieldValue = { nullValue: 0 };
  328. else if (field.resolvedType instanceof Enum && field.resolvedType.fullName === ".google.protobuf.NullValue")
  329. fieldValue = 0;
  330. else
  331. continue;
  332. } else
  333. fieldValue = readField(field, fv, options, depth);
  334. if (fieldValue === SKIP)
  335. continue;
  336. if (field.partOf) {
  337. if (seenOneofs[field.partOf.name])
  338. throw Error(type.fullName + ": multiple values for oneof " + field.partOf.name);
  339. seenOneofs[field.partOf.name] = true;
  340. }
  341. if (!isImplicitDefault(field, fieldValue))
  342. out[field.name] = fieldValue;
  343. }
  344. return out;
  345. }
  346. // --- writing messages ---
  347. function hasOwn(o, k) {
  348. return o != null && Object.prototype.hasOwnProperty.call(o, k);
  349. }
  350. function setOwn(o, k, v) {
  351. if (k === "__proto__")
  352. util.makeProp(o, k);
  353. o[k] = v;
  354. }
  355. function wktFieldName(type, name) {
  356. var field = fieldsByJsonName(type)[name];
  357. return field ? field.name : name;
  358. }
  359. function wktFieldValue(type, message, name) {
  360. var field = fieldsByJsonName(type)[name];
  361. if (!field)
  362. return message && message[name];
  363. if (hasOwn(message, field.name))
  364. return message[field.name];
  365. if (hasOwn(message, field.protoName))
  366. return message[field.protoName];
  367. if (hasOwn(message, field.jsonName))
  368. return message[field.jsonName];
  369. return undefined;
  370. }
  371. function writeScalar(type, value) {
  372. switch (type) {
  373. case "int64": case "sint64": case "sfixed64":
  374. case "uint64": case "fixed64":
  375. return value == null ? "0" : String(value);
  376. case "float": case "double":
  377. return typeof value === "number" && !isFinite(value) ? String(value) : value;
  378. case "bytes":
  379. return value == null ? "" : util.base64.encode(value, 0, value.length);
  380. default:
  381. return value;
  382. }
  383. }
  384. function writeSingular(field, value, options, depth) {
  385. if (field.resolvedType instanceof Type)
  386. return toJsonValue(field.resolvedType, value, options, depth + 1);
  387. if (field.resolvedType instanceof Enum) {
  388. if (field.resolvedType.fullName === ".google.protobuf.NullValue")
  389. return null;
  390. var name = field.resolvedType.valuesById[value];
  391. return name === undefined ? value : name;
  392. }
  393. return writeScalar(field.type, value);
  394. }
  395. function toJsonValue(type, message, options, depth) {
  396. if (depth > util.recursionLimit)
  397. throw Error("max depth exceeded");
  398. var wkt = WKT_TO[type.fullName];
  399. if (wkt)
  400. return wkt(type, message, options, depth);
  401. var out = {},
  402. fields = type.fieldsArray,
  403. i = 0;
  404. for (; i < fields.length; ++i) {
  405. var field = fields[i].resolve(),
  406. value = message[field.name];
  407. if (value == null)
  408. continue;
  409. var key = isExtension(field) ? extensionName(field) : field.jsonName;
  410. if (field.map) {
  411. var mk = Object.keys(value);
  412. if (!mk.length)
  413. continue;
  414. var longKey = LONG_TYPE[field.keyType],
  415. unsignedKey = field.keyType === "uint64" || field.keyType === "fixed64",
  416. mo = {}, ki = 0;
  417. for (; ki < mk.length; ++ki) {
  418. var outKey = longKey ? util.longFromKey(mk[ki], unsignedKey).toString() : mk[ki];
  419. setOwn(mo, outKey, writeSingular(field, value[mk[ki]], options, depth));
  420. }
  421. setOwn(out, key, mo);
  422. } else if (field.repeated) {
  423. if (!value.length)
  424. continue;
  425. var arr = new Array(value.length), j = 0;
  426. for (; j < value.length; ++j)
  427. arr[j] = writeSingular(field, value[j], options, depth);
  428. setOwn(out, key, arr);
  429. } else {
  430. if (!hasOwn(message, field.name) || isImplicitDefault(field, value))
  431. continue;
  432. setOwn(out, key, writeSingular(field, value, options, depth));
  433. }
  434. }
  435. return out;
  436. }
  437. // --- well-known types ---
  438. function longToNumber(value) {
  439. if (value == null) return 0;
  440. if (typeof value === "number") return value;
  441. if (typeof value.toNumber === "function") return value.toNumber();
  442. return Number(value) || 0;
  443. }
  444. function nanosToString(nanos) {
  445. var str = String(nanos < 0 ? -nanos : nanos);
  446. while (str.length < 9) str = "0" + str;
  447. while (str.length > 3 && str.slice(str.length - 3) === "000") str = str.slice(0, str.length - 3);
  448. return str;
  449. }
  450. function fracToNanos(frac) {
  451. while (frac.length < 9) frac += "0";
  452. return parseInt(frac.slice(0, 9), 10);
  453. }
  454. function daysInMonth(year, month) {
  455. switch (month) {
  456. case 2:
  457. return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0) ? 29 : 28;
  458. case 4:
  459. case 6:
  460. case 9:
  461. case 11:
  462. return 30;
  463. default:
  464. return 31;
  465. }
  466. }
  467. function camelToSnake(path) {
  468. return path.replace(/[A-Z]/g, function ($0) { return "_" + $0.toLowerCase(); });
  469. }
  470. var WKT_FROM = {};
  471. var WKT_TO = {};
  472. WKT_FROM[".google.protobuf.Duration"] = function (type, value) {
  473. if (typeof value !== "string")
  474. throw invalid(type.fullName, value, "expected duration string");
  475. var match = /^(-)?([0-9]+)(?:\.([0-9]{1,9}))?s$/.exec(value);
  476. if (!match)
  477. throw invalid(type.fullName, value, "invalid duration");
  478. var sign = match[1] ? -1 : 1,
  479. seconds = parseInt(match[2], 10) * sign || 0,
  480. nanos = match[3] ? fracToNanos(match[3]) * sign || 0 : 0;
  481. if (seconds > 315576000000 || seconds < -315576000000)
  482. throw invalid(type.fullName, value, "duration out of range");
  483. return { seconds: seconds, nanos: nanos };
  484. };
  485. WKT_TO[".google.protobuf.Duration"] = function (type, message) {
  486. var seconds = longToNumber(message.seconds),
  487. nanos = message.nanos || 0;
  488. if (seconds > 315576000000 || seconds < -315576000000)
  489. throw Error("google.protobuf.Duration out of range");
  490. if (nanos > 999999999 || nanos < -999999999 || seconds && nanos && seconds < 0 !== nanos < 0)
  491. throw Error("google.protobuf.Duration nanos invalid");
  492. var result = (seconds < 0 || nanos < 0 ? "-" : "") + Math.abs(seconds);
  493. if (nanos)
  494. result += "." + nanosToString(nanos);
  495. return result + "s";
  496. };
  497. WKT_FROM[".google.protobuf.Timestamp"] = function (type, value) {
  498. if (typeof value !== "string")
  499. throw invalid(type.fullName, value, "expected timestamp string");
  500. var match = /^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])T([01]\d|2[0-3]):([0-5]\d):([0-5]\d)(?:\.(\d{1,9}))?(Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/.exec(value);
  501. if (!match)
  502. throw invalid(type.fullName, value, "invalid timestamp");
  503. var year = parseInt(match[1], 10),
  504. month = parseInt(match[2], 10),
  505. day = parseInt(match[3], 10);
  506. if (day > daysInMonth(year, month))
  507. throw invalid(type.fullName, value, "invalid timestamp date");
  508. var millis = new Date(value).getTime();
  509. if (isNaN(millis))
  510. throw invalid(type.fullName, value, "invalid timestamp");
  511. var seconds = Math.floor(millis / 1000),
  512. nanos = match[7] ? fracToNanos(match[7]) : 0;
  513. if (seconds < -62135596800 || seconds > 253402300799)
  514. throw invalid(type.fullName, value, "timestamp out of range");
  515. return { seconds: seconds, nanos: nanos };
  516. };
  517. WKT_TO[".google.protobuf.Timestamp"] = function (type, message) {
  518. var seconds = longToNumber(message.seconds),
  519. nanos = message.nanos || 0;
  520. if (seconds < -62135596800 || seconds > 253402300799)
  521. throw Error("google.protobuf.Timestamp out of range");
  522. if (nanos < 0 || nanos > 999999999)
  523. throw Error("google.protobuf.Timestamp nanos out of range");
  524. var iso = new Date(seconds * 1000).toISOString();
  525. return nanos
  526. ? iso.replace(/\.\d+Z$/, "." + nanosToString(nanos) + "Z")
  527. : iso.replace(/\.\d+Z$/, "Z");
  528. };
  529. WKT_FROM[".google.protobuf.FieldMask"] = function (type, value) {
  530. if (typeof value !== "string")
  531. throw invalid(type.fullName, value, "expected field mask string");
  532. if (value.indexOf("_") !== -1)
  533. throw invalid(type.fullName, value, "field mask path must be lowerCamelCase");
  534. var paths = value.length ? value.split(",") : [],
  535. i = 0;
  536. for (; i < paths.length; ++i)
  537. paths[i] = camelToSnake(paths[i]);
  538. return { paths: paths };
  539. };
  540. WKT_TO[".google.protobuf.FieldMask"] = function (type, message) {
  541. var paths = message.paths || [],
  542. out = [],
  543. i = 0;
  544. for (; i < paths.length; ++i) {
  545. var camel = util.jsonName(paths[i]);
  546. if (camelToSnake(camel) !== paths[i])
  547. throw Error("google.protobuf.FieldMask path does not round-trip: " + paths[i]);
  548. out.push(camel);
  549. }
  550. return out.join(",");
  551. };
  552. ["DoubleValue", "FloatValue", "Int64Value", "UInt64Value", "Int32Value",
  553. "UInt32Value", "BoolValue", "StringValue", "BytesValue"].forEach(function (name) {
  554. var fullName = ".google.protobuf." + name;
  555. WKT_FROM[fullName] = function (type, value, options, depth) {
  556. return { value: readSingular(type.fields.value.resolve(), value, options, depth) };
  557. };
  558. WKT_TO[fullName] = function (type, message, options, depth) {
  559. return writeSingular(type.fields.value.resolve(), message.value, options, depth);
  560. };
  561. });
  562. function valueFromJson(json, depth) {
  563. if (depth > util.recursionLimit)
  564. throw Error("max depth exceeded");
  565. if (json === null)
  566. return { nullValue: 0 };
  567. switch (typeof json) {
  568. case "number":
  569. if (!isFinite(json))
  570. throw Error("google.protobuf.Value cannot hold a non-finite number");
  571. return { numberValue: json };
  572. case "string":
  573. validateUtf16(json, "google.protobuf.Value.string_value");
  574. return { stringValue: json };
  575. case "boolean":
  576. return { boolValue: json };
  577. }
  578. if (Array.isArray(json)) {
  579. var values = new Array(json.length), i = 0;
  580. for (; i < json.length; ++i)
  581. values[i] = valueFromJson(json[i], depth + 1);
  582. return { listValue: { values: values } };
  583. }
  584. return { structValue: { fields: structFieldsFromJson(json, depth + 1) } };
  585. }
  586. function structFieldsFromJson(json, depth) {
  587. var fields = Object.create(null), k;
  588. for (k in json)
  589. if (hasOwn(json, k)) {
  590. validateUtf16(k, "google.protobuf.Struct.fields");
  591. fields[k] = valueFromJson(json[k], depth);
  592. }
  593. return fields;
  594. }
  595. WKT_FROM[".google.protobuf.Value"] = function (type, value, options, depth) {
  596. return valueFromJson(value, depth);
  597. };
  598. WKT_FROM[".google.protobuf.Struct"] = function (type, value, options, depth) {
  599. if (value === null || typeof value !== "object" || Array.isArray(value))
  600. throw invalid(type.fullName, value, "google.protobuf.Struct must be an object");
  601. return { fields: structFieldsFromJson(value, depth + 1) };
  602. };
  603. WKT_FROM[".google.protobuf.ListValue"] = function (type, value, options, depth) {
  604. if (!Array.isArray(value))
  605. throw invalid(type.fullName, value, "google.protobuf.ListValue must be an array");
  606. var values = new Array(value.length), i = 0;
  607. for (; i < value.length; ++i)
  608. values[i] = valueFromJson(value[i], depth + 1);
  609. return { values: values };
  610. };
  611. function valueToJson(message, options, depth) {
  612. if (depth > util.recursionLimit)
  613. throw Error("max depth exceeded");
  614. if (message == null || hasOwn(message, "nullValue"))
  615. return null;
  616. if (hasOwn(message, "numberValue")) {
  617. if (typeof message.numberValue === "number" && !isFinite(message.numberValue))
  618. throw Error("google.protobuf.Value cannot hold a non-finite number");
  619. return message.numberValue;
  620. }
  621. if (hasOwn(message, "stringValue")) return message.stringValue;
  622. if (hasOwn(message, "boolValue")) return message.boolValue;
  623. if (hasOwn(message, "structValue")) return structToJson(message.structValue, options, depth + 1);
  624. if (hasOwn(message, "listValue")) return listToJson(message.listValue, options, depth + 1);
  625. return null;
  626. }
  627. function structToJson(message, options, depth) {
  628. var out = {}, fields = message && message.fields, k;
  629. if (fields)
  630. for (k in fields)
  631. if (hasOwn(fields, k))
  632. setOwn(out, k, valueToJson(fields[k], options, depth));
  633. return out;
  634. }
  635. function listToJson(message, options, depth) {
  636. var values = message && message.values;
  637. if (!values) return [];
  638. var arr = new Array(values.length), i = 0;
  639. for (; i < values.length; ++i)
  640. arr[i] = valueToJson(values[i], options, depth);
  641. return arr;
  642. }
  643. WKT_TO[".google.protobuf.Value"] = function (type, message, options, depth) {
  644. return valueToJson(message, options, depth);
  645. };
  646. WKT_TO[".google.protobuf.Struct"] = function (type, message, options, depth) {
  647. return structToJson(message, options, depth);
  648. };
  649. WKT_TO[".google.protobuf.ListValue"] = function (type, message, options, depth) {
  650. return listToJson(message, options, depth);
  651. };
  652. WKT_FROM[".google.protobuf.Any"] = function (type, value, options, depth) {
  653. if (value === null || typeof value !== "object" || Array.isArray(value))
  654. throw invalid(type.fullName, value, "google.protobuf.Any must be an object");
  655. var typeUrl = value["@type"];
  656. if (typeUrl === undefined)
  657. return {};
  658. if (typeof typeUrl !== "string")
  659. throw Error("google.protobuf.Any @type must be a string");
  660. var name = typeUrl.substring(typeUrl.lastIndexOf("/") + 1),
  661. msgType = type.root.lookupType(name),
  662. custom = WKT_FROM[msgType.fullName] !== undefined,
  663. body;
  664. if (custom)
  665. body = value.value;
  666. else {
  667. body = {};
  668. for (var k in value)
  669. if (hasOwn(value, k) && k !== "@type")
  670. setOwn(body, k, value[k]);
  671. }
  672. var inner = readMessage(msgType, body, options, depth + 1);
  673. var url = typeUrl.charAt(0) === "." ? typeUrl.slice(1) : typeUrl,
  674. out = {};
  675. if (url.indexOf("/") === -1)
  676. url = "/" + url;
  677. out[wktFieldName(type, "type_url")] = url;
  678. out[wktFieldName(type, "value")] = msgType.encode(inner).finish();
  679. return out;
  680. };
  681. WKT_TO[".google.protobuf.Any"] = function (type, message, options, depth) {
  682. var typeUrl = wktFieldValue(type, message, "type_url");
  683. if (!typeUrl)
  684. return {};
  685. var name = typeUrl.substring(typeUrl.lastIndexOf("/") + 1),
  686. msgType = type.root.lookupType(name),
  687. decoded = msgType.decode(wktFieldValue(type, message, "value")),
  688. body = toJsonValue(msgType, decoded, options, depth + 1),
  689. result;
  690. if (WKT_TO[msgType.fullName])
  691. result = { "@type": typeUrl, "value": body };
  692. else {
  693. result = { "@type": typeUrl };
  694. for (var k in body)
  695. if (hasOwn(body, k))
  696. setOwn(result, k, body[k]);
  697. }
  698. return result;
  699. };
  700. // --- duplicate keys ---
  701. // JSON.parse keeps the last duplicate key, but ProtoJSON rejects duplicates.
  702. function checkDuplicateKeys(str) {
  703. var stack = [],
  704. expectKey = false,
  705. i = 0,
  706. n = str.length;
  707. while (i < n) {
  708. var c = str.charAt(i);
  709. if (c === "{") {
  710. stack.push(Object.create(null));
  711. expectKey = true;
  712. ++i;
  713. } else if (c === "[") {
  714. stack.push(null);
  715. expectKey = false;
  716. ++i;
  717. } else if (c === "}" || c === "]") {
  718. stack.pop();
  719. expectKey = false;
  720. ++i;
  721. } else if (c === ":") {
  722. expectKey = false;
  723. ++i;
  724. } else if (c === ",") {
  725. expectKey = stack.length > 0 && stack[stack.length - 1] !== null;
  726. ++i;
  727. } else if (c === "\"") {
  728. var start = i++;
  729. while (i < n) {
  730. var ch = str.charAt(i++);
  731. if (ch === "\\") ++i;
  732. else if (ch === "\"") break;
  733. }
  734. if (expectKey) {
  735. var seen = stack[stack.length - 1],
  736. name = JSON.parse(str.slice(start, i));
  737. if (seen[name])
  738. throw Error("duplicate key in JSON object: " + JSON.stringify(name));
  739. seen[name] = true;
  740. expectKey = false;
  741. }
  742. } else
  743. ++i;
  744. }
  745. }
  746. // --- public API ---
  747. /**
  748. * ProtoJSON conversion options.
  749. * @interface IProtoJsonOptions
  750. * @property {boolean} [ignoreUnknownFields=false] Ignores unknown object members and unrecognized enum names while parsing.
  751. */
  752. /**
  753. * Parses a message from an already-parsed ProtoJSON value using the specified reflected type.
  754. * @function fromJson
  755. * @name fromJson
  756. * @param {$protobuf.Type} type Reflected message type
  757. * @param {*} json Already-parsed ProtoJSON value
  758. * @param {IProtoJsonOptions} [options] Conversion options
  759. * @returns {$protobuf.Message<{}>} Message instance
  760. */
  761. protojson.fromJson = function fromJson(type, json, options) {
  762. if (!(type instanceof Type))
  763. throw TypeError("type must be a Type");
  764. type.root.resolveAll();
  765. return type.create(readMessage(type, json, options || {}, 0));
  766. };
  767. /**
  768. * Parses a message from ProtoJSON text using the specified reflected type.
  769. * @function fromJsonString
  770. * @name fromJsonString
  771. * @param {$protobuf.Type} type Reflected message type
  772. * @param {string} json ProtoJSON text
  773. * @param {IProtoJsonOptions} [options] Conversion options
  774. * @returns {$protobuf.Message<{}>} Message instance
  775. */
  776. protojson.fromJsonString = function fromJsonString(type, json, options) {
  777. if (typeof json !== "string")
  778. throw TypeError("json must be a string");
  779. checkDuplicateKeys(json);
  780. return protojson.fromJson(type, JSON.parse(json), options);
  781. };
  782. /**
  783. * Formats a message as ProtoJSON using the specified reflected type.
  784. * @function toJson
  785. * @name toJson
  786. * @param {$protobuf.Type} type Reflected message type
  787. * @param {$protobuf.Message<{}>|Object.<string,*>} message Message instance or plain object
  788. * @param {IProtoJsonOptions} [options] Conversion options
  789. * @returns {*} ProtoJSON value (object, array, string, number, boolean or null)
  790. */
  791. protojson.toJson = function toJson(type, message, options) {
  792. if (!(type instanceof Type))
  793. throw TypeError("type must be a Type");
  794. type.root.resolveAll();
  795. return toJsonValue(type, message, options || {}, 0);
  796. };
  797. /**
  798. * Formats a message as ProtoJSON text using the specified reflected type.
  799. * @function toJsonString
  800. * @name toJsonString
  801. * @param {$protobuf.Type} type Reflected message type
  802. * @param {$protobuf.Message<{}>|Object.<string,*>} message Message instance or plain object
  803. * @param {IProtoJsonOptions} [options] Conversion options
  804. * @returns {string} ProtoJSON text
  805. */
  806. protojson.toJsonString = function toJsonString(type, message, options) {
  807. return JSON.stringify(protojson.toJson(type, message, options));
  808. };
  809. /**
  810. * Installs reflected {@link Type} convenience methods.
  811. * @function install
  812. * @name install
  813. * @returns {undefined}
  814. */
  815. protojson.install = function install() {
  816. /**
  817. * Parses a message of this type from an already-parsed ProtoJSON value. Convenience for {@link protojson.fromJson}.
  818. * @param {*} json Already-parsed ProtoJSON value
  819. * @param {IProtoJsonOptions} [options] Conversion options
  820. * @returns {Message<{}>} Message instance
  821. */
  822. Type.prototype.fromJson = function fromJson(json, options) {
  823. return protojson.fromJson(this, json, options);
  824. };
  825. /**
  826. * Parses a message of this type from ProtoJSON text. Convenience for {@link protojson.fromJsonString}.
  827. * @param {string} json ProtoJSON text
  828. * @param {IProtoJsonOptions} [options] Conversion options
  829. * @returns {Message<{}>} Message instance
  830. */
  831. Type.prototype.fromJsonString = function fromJsonString(json, options) {
  832. return protojson.fromJsonString(this, json, options);
  833. };
  834. /**
  835. * Formats a message of this type as ProtoJSON. Convenience for {@link protojson.toJson}.
  836. * @param {Message<{}>|Object.<string,*>} message Message instance or plain object
  837. * @param {IProtoJsonOptions} [options] Conversion options
  838. * @returns {*} ProtoJSON value
  839. */
  840. Type.prototype.toJson = function toJson(message, options) {
  841. return protojson.toJson(this, message, options);
  842. };
  843. /**
  844. * Formats a message of this type as ProtoJSON text. Convenience for {@link protojson.toJsonString}.
  845. * @param {Message<{}>|Object.<string,*>} message Message instance or plain object
  846. * @param {IProtoJsonOptions} [options] Conversion options
  847. * @returns {string} ProtoJSON text
  848. */
  849. Type.prototype.toJsonString = function toJsonString(message, options) {
  850. return protojson.toJsonString(this, message, options);
  851. };
  852. };