-
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
undefined instead of default for optional fields ? #1572
Comments
I’m talking about proto2. I made a first shot at an option : sloonz@c6a7638 Why is optional currently typed as |
I checked Your WIP commit looks good to me. I recently added a very minimal test for |
Added the unit tests : sloonz@a9fb6dd
Well, that commit didn’t fixed the issue, it was fixed on another one : #826 (comment) (pretty sure it was in fact fixed here : ed7e2e7) But I think it’s a discussion for another issue, one I’ll open once this one is closed ;) |
Not sure if I'm talking about the same as you, as my experience is slightly different, but related: Right now the library does not allow to have When something is missing, a typical JS/TS developer would expect a What I had to do as a workaround is quite unsatisfactory, as it makes the whole thing less efficient because it requires extra copy operations: // not present fields are not copied, and the plain object removes the problems introduced by opinionated getters
const messageFollowingJsPractices = { ...protobufjsProblematicMessage } I would make a PR allowing for |
I just made a pull request with the option and the unit tests :) |
Actually the way other languages (e.g. C++, C# see examples in https://github.com/protocolbuffers/protobuf/blob/v3.12.0/docs/field_presence.md) approach So it is an important and bearing consequence choice in design to decide what should be protobufjs's value for non-set Now 6.11.X changed it to use My current issue is however the ability to actually get the 'default type value' for those fields (as mentioned here #1406 (comment)), which was possible in 6.10.2, though maybe as an additional operation instead of having the values returned by getters as such. One more consideration is the ability to use 'prototype' features of Javascript - e.g. 6.10.2 I see that |
I'm a little bit lost here :) In 6.11.x, the changes were related to two types of fields: If your proto is |
(I fully support the idea of methods for checking the presence, like in other languages, but I think at this point it's the same as checking for a |
I was referring to Let's consider following proto definition:
Test code:
Prints following with version 6.10.2:
and following with version 6.11.2:
In fact the differences are tiny and boil down to the value returned when accessing unset optional field on the message. The value in APIs in other languages differ in this regard, i.e. unset optional field will have the 'default type value' when accessed and this was also the behavior in 6.10.2 and what my code already started to utilize. You might notice some other inconsistencies with protobuf specifications, e.g. msg1 should probably skip serializing the non-optional fields with default values (i.e. There are at least two questions here:
|
As for 6.10.2 the answers to those questions are clear:
I suppose if the current semantics is here to stay it would be useful to have some kind of |
Unfortunately, the behavior that was inherited for According to the official guidance a This all might not make a lot of sense if we look at protobuf.js as a separate thing, but if we look at the protobuf ecosystem as a whole, then, as Right now, to check the presence of an optional field, you could either make sure it exists has a non- I understand your point that there is no solution currently to get a default value for an optional field. Let me think if we could do something that makes sense here (or feel free to send a PR :) ) Now, having all that said :) what's your use case of |
I started using The specific use-case that broke is actually a bit unrelated though - since I use the same data model in the whole frontend, I also use it as backing store for my Vue.js 2.0 reactive edit screens. In there I need to get the whole object instantiated with relevant fields initialized in order to make the reactivity work (might get better in Vue.js 3.0) - for this I currently call Still, there is a large discrepancy in the semantics protobufjs exposes now (accessing unset field returns One way would be to follow my other suggestion from #1406 (comment) and add option to get the defaults for |
What kind of serialization do you have in mind? I think as long as the actual protobufjs objects do support distinguishing whether field is explicitly set or not and whether returned value is a default one from static prototype or one set on the object; and as long as serializing and deserializing such object using protobufjs's I suppose you are referring to some custom serialization like treating those objects as JS objects, using
I'm not sure what do you mean exactly by "setting any kind of default value'', this might be a matter of wording, but I don't see having a fallback when returning value as having any value set. Also note that real one-of field accessors in other languages do return default values even when you access them for unset field or field set to a different one-of case, e.g. see this implementation of C# property accessor:
I agree, though IMHO previous version of protobufjs implemented proto3 optionals closer to the spirit of their specification than the current implementation. They truly allowed one to check their presence, while still using them as regular fields as is possible in other language APIs. They also properly preserved those properties when serialized and deserialized. And now the implementation diverted from that. |
I read through this whole thread, but feel like I missed something. I'm working on a project where multiple systems are communicating utilizing proto3. I have worked on systems using C, where we make use of structures and encode and decode them, and everything is happy. I am sending data to a system written in JavaScript where I have explicitly set fields to have a value of 0 (all of the fields are set all of the time, just some happen to equal the default values). I would have expected the decoding in JavaScript to return an object analogous to the structures in C, where it has all of the fields, and the ones set to zero would be present with a value of zero. But the decoding in JavaScript is not creating the fields at all (I assume they weren't included in the encoding due to matching the default value - which is to be expected). This thread gives the impression this is expected behavior? There is a functional difference between the languages? What is the best way to get the default value in this case? Does the receiver essentially have to recreate the protobuffer definition to implement their own setting of the default value in this case? That is, if the field isn't present, use a default value that is stored elsewhere? I feel like I have to be missing something, because this doesn't seem like this is how it should work. |
Ok, yes, I was misunderstanding something. It looks like a two step process works in JavaScript where the |
The protobuf specification demands type-specific default values such as 0 for numbers when decoding. That is quite weird for TypeScript code which usually uses null or undefined for missing values. Let's create an alternative way to decode without defaults. Maybe the following issue will be resolved at some point so we would not need our own workaround: protobufjs/protobuf.js#1572
The protobuf specification demands type-specific default values such as 0 for numbers when decoding. That is quite weird for TypeScript code which usually uses null or undefined for missing values. Let's create an alternative way to decode without defaults. Maybe the following issue will be resolved at some point so we would not need our own workaround: protobufjs/protobuf.js#1572
protobuf.js version: 6.10.2
Currently, to test if an optional field has been provided, you have to use
message.hasOwnProperty("optField")
becausemessage.optField
will return the default value (0 for numbers,""
for strings) if not present in the message.While this is in line with idiomatic protobuf, it is completely out of line with idiomatic javascript where unset optional field would just return
undefined
when accessed.My suggestion is to add a pbjs option (for example
--no-optional-defaults
) for people like me that prefer the javascript way, that would setMessage.prototype.optField
toundefined
instead of the default value for the type.(for the record, I’m willing to work on this feature if you’re fine with integrating it)
The text was updated successfully, but these errors were encountered: