-
Notifications
You must be signed in to change notification settings - Fork 43
Improve JSON support; move most ser/deser from generated code into runtime library #69
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
Conversation
468ce35 to
6f68bea
Compare
seanadkinson
left a comment
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.
Very cool... excited to upgrade to this!
runtime/src/commonMain/kotlin/pbandk/json/JsonWireMarshaller.kt
Outdated
Show resolved
Hide resolved
runtime/src/commonMain/kotlin/pbandk/json/JsonWireMarshaller.kt
Outdated
Show resolved
Hide resolved
runtime/src/commonMain/kotlin/pbandk/json/JsonWireUnmarshaller.kt
Outdated
Show resolved
Hide resolved
|
A couple things I meant to mention:
|
6f68bea to
eb5e3cf
Compare
|
@seanadkinson This is finally ready for review. One small fix led to another and I ended up converting all of the binary marshall/unmarshall code as well 😁 The new code happens to fix some additional conformance tests we were previously failing. I'll create GitHub issues for the remaining gaps in our JSON support. |
dustinbrown
left a comment
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.
Quite the change set, looks good to me.
seanadkinson
left a comment
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.
Couple questions, but overall looks really clean. Love all the failed tests we get to remove 👍
| sizeFn: (T) -> Int | ||
| ) { | ||
| val valueType = type.messageCompanion.fieldDescriptors[0].type | ||
| if (valueType.isDefaultValue(value)) { |
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.
Theres another default value check up on line 14. Is one of these not needed?
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.
They're slightly different for wrapper types. Using the StringValue wrapper type as an example:
- The call on line 14 is doing
!fd.type.hasPresence && fd.type.isDefaultValue(value).StringValueis a message type and message types always "have presence" (i.e. they're nullable), so thefd.type.isDefaultValue(value)check won't even be called on line 14. - Here on line 62, we've looked up the underlying type of the
StringValuewrapper:String. We're now checking ifvalueis the default value ofString(notStringValue). If it is, we'll omit writing the empty string on the wire. But we're still writing theStringValuemessage header so the receiver knows that the value was non-null.
runtime/src/commonMain/kotlin/pbandk/internal/json/JsonMessageMarshaller.kt
Show resolved
Hide resolved
| import pbandk.protobufjs.Writer | ||
| import pbandk.protobufjs.protobufjsLong | ||
|
|
||
| private fun Writer.writeValueNoTag(type: FieldDescriptor.Type, value: Any) { |
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.
Is this code unable to use the JsonValueMarshaller and related classes from commonMain? I guess I'm unclear about the relation of this class (and CodedStreamBinaryWireMarshaller below) to the ones in commonMain.
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.
I think you're confusing the JSON marshallers and the "binary" marshallers. ProtobufjsBinaryWireMarshaller and CodedStreamBinaryWireMarshaller are both responsible for converting a field into protobuf binary format. Whereas JsonValueMarshaller is responsible for converting a field into protobuf JSON format.
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.
Yes, sorry, I understand the different between the JSON and the Binary - bad example specifying JsonValueMarshaller in my comment.
The point I was trying to make was that it seemed like there was a lot of duplicate work being done in this jsMain module, that is already done in commonMain, but looking closer, this probably isn't the case. I guess I just saw enough when statements that rolled through each type, either reading or writing the value, and I thought we wouldn't need to do that outside of commonMain. But if I understand correctly, this code is just providing the javascript bindings of doing the actual reading/writing, and code up in commonMain is using this marshaller for doing the work in javascript. Is my understanding correct?
0d4c15e to
e98834e
Compare
|
Now that the Kotlin/Native PR finally got merged, I've rebased on top of that one. I've also added a detailed description to this PR with all of the changes being made. I'll merge this as soon as the tests pass. |
* Rewrote JSON support to better implement the proto3 JSON spec. This includes support for the `json_name` protobuf option. * Added `JsonConfig` class that can be used for configuring JSON marshalling/unmarshalling at runtime. Currently supported configuration includes `ignoreUnknownFieldsInInput`, `outputDefaultValues`, and `outputProtoFieldNames`, which match the options described at https://developers.google.com/protocol-buffers/docs/proto3#json_options. * Got rid of the need for projects using `pbandk` to use the `kotlinx-serialization` gradle plugin and add a dependency on the `kotlinx-serialization` library. The library is now an internal implementation detail of `pbandk`. * Moved all of the binary marshalling functionality and most of the binary unmarshalling functionality from the generated code to the runtime library. * Added `protoMarshal(OutputStream)`, `protoUnmarshal(InputStream)`, and `protoUnmarshal(ByteBuffer)` overloads on the JVM. * Fixed some bugs with handling of `packed` fields, marshalling of enums in Javascript, and base64 encoding/decoding in Javascript. Breaking API changes: * Changed `Message` so that it no longer needs to extend from itself. * Added `@PbandkInternal` and `@PublicForGeneratedCode` annotations on relevant portions of the public API that are only public for pbandk's internal use. * The below methods are now defined as extension methods rather than being part of the `Message` interface. Code that calls these methods will now need to import them first. * `Message.jsonMarshal()` * `Message.Companion.jsonUnmarshal(String)` * `Message.protoMarshal()` * `Message.Companion.protoUnmarshal(ByteArray)` * These two method overloads: * `Message.jsonMarshal(kotlinx.serialization.json.Json)` * `Message.Companion.jsonUnmarshal(kotlinx.serialization.json.Json, String)` have been replaced with: * `Message.jsonMarshal(pbandk.json.JsonConfig)` * `Message.Companion.jsonUnmarshal(String, pbandk.json.JsonConfig)` * These two method overloads: * `Message.protoMarshal(pbandk.Marshaller)` * `Message.Companion.protoUnmarshal(pbandk.Unmarshaller)` have been replaced with: * `Message.marshal(pbandk.MessageMarshaller)` * `Message.Companion.unmarshal(pbandk.MessageUnmarshaller)` * Replaced `Marshaller` and `Unmarshaller` interfaces with `MessageMarshaller` and `MessageUnmarshaller`, which are much simpler and function differently from the previous interfaces. * Removed `Sizer` and `Util` from the public API. * Removed `UnknownField` constructors and the `UnknownField.size()` method from the public API. * `MessageMap.entries` is now a `Set` instead of a `List`. Fixes #23, fixes #61. Portions of the proto3 JSON spec that still need to be implemented are tracked in #72.
e98834e to
1c88951
Compare
Rewrote JSON support to better implement the proto3 JSON spec. This includes support for the
json_nameprotobuf option.Added
JsonConfigclass that can be used for configuring JSON marshalling/unmarshalling at runtime. Currently supported configuration includesignoreUnknownFieldsInInput,outputDefaultValues, andoutputProtoFieldNames, which match the options described at https://developers.google.com/protocol-buffers/docs/proto3#json_options.Got rid of the need for projects using
pbandkto use thekotlinx-serializationgradle plugin and add a dependency on thekotlinx-serializationlibrary. The library is now an internal implementation detail ofpbandk.Moved all of the binary marshalling functionality and most of the binary unmarshalling functionality from the generated code to the runtime library.
Added
protoMarshal(OutputStream),protoUnmarshal(InputStream), andprotoUnmarshal(ByteBuffer)overloads on the JVM.Fixed some bugs with handling of
packedfields, marshalling of enums in Javascript, and base64 encoding/decoding in Javascript.Breaking API changes:
Changed
Messageso that it no longer needs to extend from itself.Added
@PbandkInternaland@PublicForGeneratedCodeannotations on relevant portions of the public API that are only public for pbandk's internal use.The below methods are now defined as extension methods rather than being part of the
Messageinterface. Code that calls these methods will now need to import them first.Message.jsonMarshal()Message.Companion.jsonUnmarshal(String)Message.protoMarshal()Message.Companion.protoUnmarshal(ByteArray)These two method overloads:
Message.jsonMarshal(kotlinx.serialization.json.Json)Message.Companion.jsonUnmarshal(kotlinx.serialization.json.Json, String)have been replaced with:
Message.jsonMarshal(pbandk.json.JsonConfig)Message.Companion.jsonUnmarshal(String, pbandk.json.JsonConfig)These two method overloads:
Message.protoMarshal(pbandk.Marshaller)Message.Companion.protoUnmarshal(pbandk.Unmarshaller)have been replaced with:
Message.marshal(pbandk.MessageMarshaller)Message.Companion.unmarshal(pbandk.MessageUnmarshaller)Replaced
MarshallerandUnmarshallerinterfaces withMessageMarshallerandMessageUnmarshaller, which are much simpler and function differently from the previous interfaces.Removed
SizerandUtilfrom the public API.Removed
UnknownFieldconstructors and theUnknownField.size()method from the public API.MessageMap.entriesis now aSetinstead of aList.Fixes #23, fixes #61. Portions of the proto3 JSON spec that still need to be implemented are tracked in #72.