Skip to content

Commit eb5e3cf

Browse files
committed
Refactor JSON support to better implement the proto3 JSON spec
* Get 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`. * Change `Message` so that it no longer needs to extend from itself. * Some API changes to `Message.jsonMarshal()`, `Message.jsonUnmarshal()`, `MessageMap.entries`.
1 parent 9969b33 commit eb5e3cf

File tree

60 files changed

+7722
-6208
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+7722
-6208
lines changed

README.md

Lines changed: 68 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -84,29 +84,57 @@ message AddressBook {
8484
The following file will be generated at `tutorial/addressbook.kt`:
8585

8686
```kotlin
87-
@file:UseSerializers(pbandk.ser.TimestampSerializer::class)
88-
8987
package tutorial
9088

91-
import kotlinx.serialization.*
92-
import kotlinx.serialization.json.*
93-
9489
data class Person(
9590
val name: String = "",
9691
val id: Int = 0,
9792
val email: String = "",
9893
val phones: List<tutorial.Person.PhoneNumber> = emptyList(),
9994
val lastUpdated: pbandk.wkt.Timestamp? = null,
10095
val unknownFields: Map<Int, pbandk.UnknownField> = emptyMap()
101-
) : pbandk.Message<Person> {
102-
override operator fun plus(other: Person?) = protoMergeImpl(other)
96+
) : pbandk.Message {
97+
override operator fun plus(other: pbandk.Message?) = protoMergeImpl(other)
98+
override val fieldDescriptors get() = Companion.fieldDescriptors
10399
override val protoSize by lazy { protoSizeImpl() }
104100
override fun protoMarshal(m: pbandk.Marshaller) = protoMarshalImpl(m)
105-
override fun jsonMarshal(json: Json) = jsonMarshalImpl(json)
106101
companion object : pbandk.Message.Companion<Person> {
107102
val defaultInstance by lazy { Person() }
108103
override fun protoUnmarshal(u: pbandk.Unmarshaller) = Person.protoUnmarshalImpl(u)
109-
override fun jsonUnmarshal(json: Json, data: String) = Person.jsonUnmarshalImpl(json, data)
104+
override fun unmarshal(u: pbandk.WireUnmarshaller) = Person.unmarshalImpl(u)
105+
106+
override val fieldDescriptors: List<pbandk.FieldDescriptor> = listOf(
107+
pbandk.FieldDescriptor(
108+
name = "name",
109+
number = 1,
110+
type = pbandk.FieldDescriptor.Type.Primitive.String,
111+
value = Person::name
112+
),
113+
pbandk.FieldDescriptor(
114+
name = "id",
115+
number = 2,
116+
type = pbandk.FieldDescriptor.Type.Primitive.Int32,
117+
value = Person::id
118+
),
119+
pbandk.FieldDescriptor(
120+
name = "email",
121+
number = 3,
122+
type = pbandk.FieldDescriptor.Type.Primitive.String,
123+
value = Person::email
124+
),
125+
pbandk.FieldDescriptor(
126+
name = "phones",
127+
number = 4,
128+
type = pbandk.FieldDescriptor.Type.Repeated(valueType = pbandk.FieldDescriptor.Type.Message(messageCompanion = tutorial.Person.PhoneNumber.Companion)),
129+
value = Person::phones
130+
),
131+
pbandk.FieldDescriptor(
132+
name = "last_updated",
133+
number = 5,
134+
type = pbandk.FieldDescriptor.Type.Message(messageCompanion = pbandk.wkt.Timestamp.Companion),
135+
value = Person::lastUpdated
136+
)
137+
)
110138
}
111139

112140
sealed class PhoneType(override val value: Int, override val name: String? = null) : pbandk.Message.Enum {
@@ -130,31 +158,55 @@ data class Person(
130158
val number: String = "",
131159
val type: tutorial.Person.PhoneType = tutorial.Person.PhoneType.fromValue(0),
132160
val unknownFields: Map<Int, pbandk.UnknownField> = emptyMap()
133-
) : pbandk.Message<Person.PhoneNumber> {
134-
override operator fun plus(other: Person.PhoneNumber?) = protoMergeImpl(other)
161+
) : pbandk.Message {
162+
override operator fun plus(other: pbandk.Message?) = protoMergeImpl(other)
163+
override val fieldDescriptors get() = Companion.fieldDescriptors
135164
override val protoSize by lazy { protoSizeImpl() }
136165
override fun protoMarshal(m: pbandk.Marshaller) = protoMarshalImpl(m)
137-
override fun jsonMarshal(json: Json) = jsonMarshalImpl(json)
138166
companion object : pbandk.Message.Companion<Person.PhoneNumber> {
139167
val defaultInstance by lazy { Person.PhoneNumber() }
140168
override fun protoUnmarshal(u: pbandk.Unmarshaller) = Person.PhoneNumber.protoUnmarshalImpl(u)
141-
override fun jsonUnmarshal(json: Json, data: String) = Person.PhoneNumber.jsonUnmarshalImpl(json, data)
169+
override fun unmarshal(u: pbandk.WireUnmarshaller) = Person.PhoneNumber.unmarshalImpl(u)
170+
171+
override val fieldDescriptors: List<pbandk.FieldDescriptor> = listOf(
172+
pbandk.FieldDescriptor(
173+
name = "number",
174+
number = 1,
175+
type = pbandk.FieldDescriptor.Type.Primitive.String,
176+
value = PhoneNumber::number
177+
),
178+
pbandk.FieldDescriptor(
179+
name = "type",
180+
number = 2,
181+
type = pbandk.FieldDescriptor.Type.Enum(enumCompanion = tutorial.Person.PhoneType.Companion),
182+
value = PhoneNumber::type
183+
)
184+
)
142185
}
143186
}
144187
}
145188

146189
data class AddressBook(
147190
val people: List<tutorial.Person> = emptyList(),
148191
val unknownFields: Map<Int, pbandk.UnknownField> = emptyMap()
149-
) : pbandk.Message<AddressBook> {
192+
) : pbandk.Message {
150193
override operator fun plus(other: AddressBook?) = protoMergeImpl(other)
194+
override val fieldDescriptors get() = Companion.fieldDescriptors
151195
override val protoSize by lazy { protoSizeImpl() }
152196
override fun protoMarshal(m: pbandk.Marshaller) = protoMarshalImpl(m)
153-
override fun jsonMarshal(json: Json) = jsonMarshalImpl(json)
154197
companion object : pbandk.Message.Companion<AddressBook> {
155198
val defaultInstance by lazy { AddressBook() }
156199
override fun protoUnmarshal(u: pbandk.Unmarshaller) = AddressBook.protoUnmarshalImpl(u)
157-
override fun jsonUnmarshal(json: Json, data: String) = AddressBook.jsonUnmarshalImpl(json, data)
200+
override fun unmarshal(u: pbandk.WireUnmarshaller) = AddressBook.unmarshalImpl(u)
201+
202+
override val fieldDescriptors: List<pbandk.FieldDescriptor> = listOf(
203+
pbandk.FieldDescriptor(
204+
name = "people",
205+
number = 1,
206+
type = pbandk.FieldDescriptor.Type.Repeated(valueType = pbandk.FieldDescriptor.Type.Message(messageCompanion = tutorial.Person.Companion)),
207+
value = AddressBook::people
208+
)
209+
)
158210
}
159211
}
160212

build.gradle.kts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import org.gradle.api.tasks.testing.logging.TestLogEvent
55

66
plugins {
77
kotlin("multiplatform") version Versions.kotlin apply false
8-
kotlin("plugin.serialization") version Versions.kotlin apply false
98
id("org.springframework.boot") version Versions.springBootGradlePlugin apply false
109
}
1110

conformance/js/failing_tests.txt

Lines changed: 11 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -29,104 +29,25 @@ Required.Proto3.JsonInput.AnyWithStruct.ProtobufOutput
2929
Required.Proto3.JsonInput.AnyWithTimestamp.ProtobufOutput
3030
Required.Proto3.JsonInput.AnyWithValueForInteger.ProtobufOutput
3131
Required.Proto3.JsonInput.AnyWithValueForJsonObject.ProtobufOutput
32-
Required.Proto3.JsonInput.BoolFieldTrue.ProtobufOutput
33-
Required.Proto3.JsonInput.BoolMapEscapedKey.ProtobufOutput
34-
Required.Proto3.JsonInput.BoolMapField.ProtobufOutput
35-
Required.Proto3.JsonInput.BytesField.ProtobufOutput
36-
Required.Proto3.JsonInput.BytesRepeatedField.ProtobufOutput
37-
Required.Proto3.JsonInput.DoubleFieldInfinity.ProtobufOutput
38-
Required.Proto3.JsonInput.DoubleFieldMaxNegativeValue.ProtobufOutput
39-
Required.Proto3.JsonInput.DoubleFieldMaxPositiveValue.ProtobufOutput
40-
Required.Proto3.JsonInput.DoubleFieldMinNegativeValue.ProtobufOutput
41-
Required.Proto3.JsonInput.DoubleFieldMinPositiveValue.ProtobufOutput
42-
Required.Proto3.JsonInput.DoubleFieldNan.ProtobufOutput
43-
Required.Proto3.JsonInput.DoubleFieldNegativeInfinity.ProtobufOutput
44-
Required.Proto3.JsonInput.DoubleFieldQuotedValue.ProtobufOutput
4532
Required.Proto3.JsonInput.DurationMaxValue.ProtobufOutput
4633
Required.Proto3.JsonInput.DurationMinValue.ProtobufOutput
4734
Required.Proto3.JsonInput.DurationRepeatedValue.ProtobufOutput
4835
Required.Proto3.JsonInput.EmptyFieldMask.ProtobufOutput
49-
Required.Proto3.JsonInput.EnumFieldNumericValueNonZero.ProtobufOutput
50-
Required.Proto3.JsonInput.EnumFieldWithAlias.ProtobufOutput
51-
Required.Proto3.JsonInput.EnumFieldWithAliasDifferentCase.ProtobufOutput
52-
Required.Proto3.JsonInput.EnumFieldWithAliasLowerCase.ProtobufOutput
53-
Required.Proto3.JsonInput.EnumFieldWithAliasUseAlias.ProtobufOutput
54-
Required.Proto3.JsonInput.EnumRepeatedField.ProtobufOutput
5536
Required.Proto3.JsonInput.FieldMask.ProtobufOutput
5637
Required.Proto3.JsonInput.FieldNameInSnakeCase.ProtobufOutput
57-
Required.Proto3.JsonInput.FieldNameWithMixedCases.ProtobufOutput
58-
Required.Proto3.JsonInput.FieldNameWithNumbers.ProtobufOutput
59-
Required.Proto3.JsonInput.FloatFieldInfinity.ProtobufOutput
60-
Required.Proto3.JsonInput.FloatFieldMaxNegativeValue.ProtobufOutput
61-
Required.Proto3.JsonInput.FloatFieldMaxPositiveValue.ProtobufOutput
62-
Required.Proto3.JsonInput.FloatFieldMinNegativeValue.ProtobufOutput
63-
Required.Proto3.JsonInput.FloatFieldMinPositiveValue.ProtobufOutput
64-
Required.Proto3.JsonInput.FloatFieldNan.ProtobufOutput
65-
Required.Proto3.JsonInput.FloatFieldNegativeInfinity.ProtobufOutput
66-
Required.Proto3.JsonInput.FloatFieldQuotedValue.ProtobufOutput
67-
Required.Proto3.JsonInput.HelloWorld.ProtobufOutput
6838
Required.Proto3.JsonInput.Int32FieldExponentialFormat.ProtobufOutput
6939
Required.Proto3.JsonInput.Int32FieldFloatTrailingZero.ProtobufOutput
7040
Required.Proto3.JsonInput.Int32FieldMaxFloatValue.ProtobufOutput
71-
Required.Proto3.JsonInput.Int32FieldMaxValue.ProtobufOutput
7241
Required.Proto3.JsonInput.Int32FieldMinFloatValue.ProtobufOutput
73-
Required.Proto3.JsonInput.Int32FieldMinValue.ProtobufOutput
74-
Required.Proto3.JsonInput.Int32FieldStringValue.ProtobufOutput
75-
Required.Proto3.JsonInput.Int32FieldStringValueEscaped.ProtobufOutput
76-
Required.Proto3.JsonInput.Int32MapEscapedKey.ProtobufOutput
77-
Required.Proto3.JsonInput.Int32MapField.ProtobufOutput
78-
Required.Proto3.JsonInput.Int64FieldMaxValue.ProtobufOutput
79-
Required.Proto3.JsonInput.Int64FieldMaxValueNotQuoted.ProtobufOutput
80-
Required.Proto3.JsonInput.Int64FieldMinValue.ProtobufOutput
81-
Required.Proto3.JsonInput.Int64FieldMinValueNotQuoted.ProtobufOutput
82-
Required.Proto3.JsonInput.Int64MapEscapedKey.ProtobufOutput
83-
Required.Proto3.JsonInput.Int64MapField.ProtobufOutput
84-
Required.Proto3.JsonInput.MessageField.ProtobufOutput
85-
Required.Proto3.JsonInput.MessageMapField.ProtobufOutput
86-
Required.Proto3.JsonInput.MessageRepeatedField.ProtobufOutput
87-
Required.Proto3.JsonInput.OptionalBoolWrapper.ProtobufOutput
88-
Required.Proto3.JsonInput.OptionalBytesWrapper.ProtobufOutput
89-
Required.Proto3.JsonInput.OptionalDoubleWrapper.ProtobufOutput
90-
Required.Proto3.JsonInput.OptionalFloatWrapper.ProtobufOutput
91-
Required.Proto3.JsonInput.OptionalInt32Wrapper.ProtobufOutput
92-
Required.Proto3.JsonInput.OptionalInt64Wrapper.ProtobufOutput
93-
Required.Proto3.JsonInput.OptionalStringWrapper.ProtobufOutput
94-
Required.Proto3.JsonInput.OptionalUint32Wrapper.ProtobufOutput
95-
Required.Proto3.JsonInput.OptionalUint64Wrapper.ProtobufOutput
96-
Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput
9742
Required.Proto3.JsonInput.PrimitiveRepeatedField.ProtobufOutput
98-
Required.Proto3.JsonInput.RepeatedBoolWrapper.ProtobufOutput
99-
Required.Proto3.JsonInput.RepeatedBytesWrapper.ProtobufOutput
100-
Required.Proto3.JsonInput.RepeatedDoubleWrapper.ProtobufOutput
101-
Required.Proto3.JsonInput.RepeatedFloatWrapper.ProtobufOutput
102-
Required.Proto3.JsonInput.RepeatedInt32Wrapper.ProtobufOutput
103-
Required.Proto3.JsonInput.RepeatedInt64Wrapper.ProtobufOutput
10443
Required.Proto3.JsonInput.RepeatedListValue.ProtobufOutput
105-
Required.Proto3.JsonInput.RepeatedStringWrapper.ProtobufOutput
106-
Required.Proto3.JsonInput.RepeatedUint32Wrapper.ProtobufOutput
107-
Required.Proto3.JsonInput.RepeatedUint64Wrapper.ProtobufOutput
10844
Required.Proto3.JsonInput.RepeatedValue.ProtobufOutput
109-
Required.Proto3.JsonInput.StringField.ProtobufOutput
110-
Required.Proto3.JsonInput.StringFieldEscape.ProtobufOutput
111-
Required.Proto3.JsonInput.StringFieldSurrogatePair.ProtobufOutput
112-
Required.Proto3.JsonInput.StringFieldUnicode.ProtobufOutput
113-
Required.Proto3.JsonInput.StringFieldUnicodeEscape.ProtobufOutput
114-
Required.Proto3.JsonInput.StringFieldUnicodeEscapeWithLowercaseHexLetters.ProtobufOutput
115-
Required.Proto3.JsonInput.StringRepeatedField.ProtobufOutput
11645
Required.Proto3.JsonInput.Struct.ProtobufOutput
11746
Required.Proto3.JsonInput.StructWithEmptyListValue.ProtobufOutput
118-
Required.Proto3.JsonInput.TimestampLeap.ProtobufOutput
119-
Required.Proto3.JsonInput.TimestampMaxValue.ProtobufOutput
120-
Required.Proto3.JsonInput.TimestampMinValue.ProtobufOutput
121-
Required.Proto3.JsonInput.TimestampRepeatedValue.ProtobufOutput
122-
Required.Proto3.JsonInput.TimestampWithNegativeOffset.ProtobufOutput
123-
Required.Proto3.JsonInput.TimestampWithPositiveOffset.ProtobufOutput
12447
Required.Proto3.JsonInput.Uint32FieldMaxFloatValue.ProtobufOutput
12548
Required.Proto3.JsonInput.Uint32FieldMaxValue.ProtobufOutput
126-
Required.Proto3.JsonInput.Uint32MapField.ProtobufOutput
12749
Required.Proto3.JsonInput.Uint64FieldMaxValue.ProtobufOutput
12850
Required.Proto3.JsonInput.Uint64FieldMaxValueNotQuoted.ProtobufOutput
129-
Required.Proto3.JsonInput.Uint64MapField.ProtobufOutput
13051
Required.Proto3.JsonInput.ValueAcceptBool.ProtobufOutput
13152
Required.Proto3.JsonInput.ValueAcceptFloat.ProtobufOutput
13253
Required.Proto3.JsonInput.ValueAcceptInteger.ProtobufOutput
@@ -135,6 +56,17 @@ Required.Proto3.JsonInput.ValueAcceptNull.ProtobufOutput
13556
Required.Proto3.JsonInput.ValueAcceptObject.ProtobufOutput
13657
Required.Proto3.JsonInput.ValueAcceptString.ProtobufOutput
13758
##
59+
## More JSON failures that are JS specific
60+
##
61+
## These all seem to be related to buggy bytes-handling in our code on Kotlin/JS
62+
Required.Proto3.JsonInput.BytesField.ProtobufOutput
63+
Required.Proto3.JsonInput.BytesRepeatedField.ProtobufOutput
64+
Required.Proto3.JsonInput.OptionalBytesWrapper.ProtobufOutput
65+
Required.Proto3.JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput
66+
Required.Proto3.JsonInput.RepeatedBytesWrapper.ProtobufOutput
67+
Required.Proto3.JsonInput.TimestampMaxValue.ProtobufOutput
68+
Required.Proto3.JsonInput.TimestampRepeatedValue.ProtobufOutput
69+
##
13870
## These failures need to be investigated
13971
##
14072
## See https://github.com/streem/pbandk/issues/22

0 commit comments

Comments
 (0)