-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement wrapper for google.protobuf.Timestamp, and correctly generate wrappers for static target. #1258
base: master
Are you sure you want to change the base?
Implement wrapper for google.protobuf.Timestamp, and correctly generate wrappers for static target. #1258
Changes from all commits
8931805
19d513d
d71bc93
114ecc9
c3134e0
f274f40
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -8,6 +8,7 @@ | |||||||||||||||
var wrappers = exports; | ||||||||||||||||
|
||||||||||||||||
var Message = require("./message"); | ||||||||||||||||
var $root; | ||||||||||||||||
|
||||||||||||||||
/** | ||||||||||||||||
* From object converter part of an {@link IWrapper}. | ||||||||||||||||
|
@@ -38,7 +39,7 @@ var Message = require("./message"); | |||||||||||||||
// Custom wrapper for Any | ||||||||||||||||
wrappers[".google.protobuf.Any"] = { | ||||||||||||||||
|
||||||||||||||||
fromObject: function(object) { | ||||||||||||||||
fromObject: function fromObject(object) { | ||||||||||||||||
|
||||||||||||||||
// unwrap value type if mapped | ||||||||||||||||
if (object && object["@type"]) { | ||||||||||||||||
|
@@ -59,7 +60,7 @@ wrappers[".google.protobuf.Any"] = { | |||||||||||||||
return this.fromObject(object); | ||||||||||||||||
}, | ||||||||||||||||
|
||||||||||||||||
toObject: function(message, options) { | ||||||||||||||||
toObject: function toObject(message, options) { | ||||||||||||||||
|
||||||||||||||||
// decode value if requested and unmapped | ||||||||||||||||
if (options && options.json && message.type_url && message.value) { | ||||||||||||||||
|
@@ -81,3 +82,79 @@ wrappers[".google.protobuf.Any"] = { | |||||||||||||||
return this.toObject(message, options); | ||||||||||||||||
} | ||||||||||||||||
}; | ||||||||||||||||
|
||||||||||||||||
// Custom wrapper for Timestamp. | ||||||||||||||||
// | ||||||||||||||||
// Implements the JSON serialization / deserialization as specified by | ||||||||||||||||
// proto specification. | ||||||||||||||||
// | ||||||||||||||||
// https://github.com/protocolbuffers/protobuf/blob/5bc250b084b88b6ec98046054f5836b6b60132ef/src/google/protobuf/timestamp.proto#L101 | ||||||||||||||||
wrappers[".google.protobuf.Timestamp"] = { | ||||||||||||||||
fromObject: function fromObject(object) { | ||||||||||||||||
if (typeof object !== 'string') { | ||||||||||||||||
// for the static target, include the generated code. | ||||||||||||||||
if ($root) { | ||||||||||||||||
if (object instanceof $root.google.protobuf.Timestamp) | ||||||||||||||||
return object; | ||||||||||||||||
var message = new $root.google.protobuf.Timestamp(); | ||||||||||||||||
if (object.seconds != null) | ||||||||||||||||
if ($util.Long) | ||||||||||||||||
(message.seconds = $util.Long.fromValue(object.seconds)).unsigned = false; | ||||||||||||||||
else if (typeof object.seconds === "string") | ||||||||||||||||
message.seconds = parseInt(object.seconds, 10); | ||||||||||||||||
else if (typeof object.seconds === "number") | ||||||||||||||||
message.seconds = object.seconds; | ||||||||||||||||
else if (typeof object.seconds === "object") | ||||||||||||||||
message.seconds = new $util.LongBits(object.seconds.low >>> 0, object.seconds.high >>> 0).toNumber(); | ||||||||||||||||
if (object.nanos != null) | ||||||||||||||||
message.nanos = object.nanos | 0; | ||||||||||||||||
return message; | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
return this.fromObject(object); | ||||||||||||||||
} | ||||||||||||||||
//Convert ISO-8601 to epoch millis | ||||||||||||||||
var dt = Date.parse(object); | ||||||||||||||||
if (isNaN(dt)) { | ||||||||||||||||
// not a number, default to the parent implementation. | ||||||||||||||||
return this.fromObject(object); | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
return this.create({ | ||||||||||||||||
seconds: Math.floor(dt/1000), | ||||||||||||||||
nanos: (dt % 1000) * 1000000 | ||||||||||||||||
}); | ||||||||||||||||
}, | ||||||||||||||||
|
||||||||||||||||
toObject: function toObject(message, options) { | ||||||||||||||||
// TODO: question for reviewer, how do we want to make this backwards | ||||||||||||||||
// compatible in a more explicit way. it seems dangerous to assume | ||||||||||||||||
// that anyone who was using .toJSON() was not relying on the old | ||||||||||||||||
// behaviour. | ||||||||||||||||
if (!options) | ||||||||||||||||
options = {}; | ||||||||||||||||
|
||||||||||||||||
// decode value if requested | ||||||||||||||||
if (options && options.json) { | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||||||
return new Date(message.seconds*1000 + message.nanos/1000000).toISOString(); | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be very cool to comply with the 0, 3, 6 or 9 fractional digits rule from https://developers.google.com/protocol-buffers/docs/proto3#json Example implementation: https://github.com/gogo/protobuf/blob/v1.3.1/jsonpb/jsonpb.go#L250-L266 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, I think this needs to be fixed before this can be merged. We did this on our internal patch. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
(needs to be updated to handle 6 and 9 points of precision). |
||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
var object = {}; | ||||||||||||||||
if (options.defaults) { | ||||||||||||||||
if ($util.Long) { | ||||||||||||||||
var long = new $util.Long(0, 0, false); | ||||||||||||||||
object.seconds = options.longs === String ? long.toString() : options.longs === Number ? long.toNumber() : long; | ||||||||||||||||
} else | ||||||||||||||||
object.seconds = options.longs === String ? "0" : 0; | ||||||||||||||||
object.nanos = 0; | ||||||||||||||||
} | ||||||||||||||||
if (message.seconds != null && message.hasOwnProperty("seconds")) | ||||||||||||||||
if (typeof message.seconds === "number") | ||||||||||||||||
object.seconds = options.longs === String ? String(message.seconds) : message.seconds; | ||||||||||||||||
else | ||||||||||||||||
object.seconds = options.longs === String ? $util.Long.prototype.toString.call(message.seconds) : options.longs === Number ? new $util.LongBits(message.seconds.low >>> 0, message.seconds.high >>> 0).toNumber() : message.seconds; | ||||||||||||||||
if (message.nanos != null && message.hasOwnProperty("nanos")) | ||||||||||||||||
object.nanos = message.nanos; | ||||||||||||||||
return object; | ||||||||||||||||
} | ||||||||||||||||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
var tape = require("tape"); | ||
|
||
var protobuf = require(".."); | ||
|
||
var root = protobuf.Root.fromJSON({ | ||
}).addJSON(protobuf.common["google/protobuf/timestamp.proto"].nested).resolveAll(); | ||
|
||
var Timestamp = root.lookupType("protobuf.Timestamp"); | ||
var Long = protobuf.util.Long; | ||
|
||
tape.test("google.protobuf.Timestamp", function(test) { | ||
var timestamp = Timestamp.fromObject({ | ||
seconds: 5, | ||
nanos: 1001, | ||
}); | ||
test.ok(timestamp instanceof Timestamp.ctor, "should convert to Timestamp in fromObject"); | ||
test.same(timestamp, Timestamp.create({ seconds: new Long(5), nanos: 1001 }), "fromObject should work with raw object representation"); | ||
|
||
var jsonObj = Timestamp.toObject(timestamp, { json: true }); | ||
test.same(jsonObj, '1970-01-01T00:00:05.000Z', "correctly follows proto3 serialization for timestamps when requested"); | ||
|
||
var obj = Timestamp.toObject(timestamp); | ||
test.same(obj, { seconds: new Long(5), nanos: 1001 }, "correctly follows non proto3 serialization for timestamps when not requested"); | ||
|
||
test.end(); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This implementation cuts off information, since native
Date
can only store 3 fractional digits:It is not too hard to implement the parser manually, allowing to keep the precision.