proto, encoding/protojson, encoding/prototext: use Resolver interface
Instead of accepting a concrete protoregistry.Types type,
accept an interface that provides the necessary functionality
to perform the serialization.
The advantages of this approach:
* There is no need for complex logic to allow a Parent or custom
Resolver on the protoregistry.Types type.
* Users can pass their own custom resolver implementations directly
to the serialization functions.
* This is a more principled approach to plumbing custom resolvers
than the previous approach of overloading behavior on the concrete
Types type.
The disadvantages of this approach:
* A pointer to a concrete type is 8B, while an interface is 16B.
However, the expansion of the {Marshal,Unmarshal}Options structs
should be a concern solved separately from how to plumb custom resolvers.
* The resolver interfaces as defined today may be insufficient to
provide functionality needed in the future if protobuf expands its
feature set. For example, let's suppose the Any message permits
directly representing a enum by name. This would require the ability
to lookup an enum by name. To support that hypothetical need,
we can document that the serializers type-assert the provided Resolver
to a EnumTypeResolver and use that if possible. There is some loss
of type safety with this approach, but provides a clear path forward.
Change-Id: I81ca80e59335d36be6b43d57ec8e17abfdfa3bad
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/177044
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/encoding/protojson/decode.go b/encoding/protojson/decode.go
index 99e1a8b..a40d1e2 100644
--- a/encoding/protojson/decode.go
+++ b/encoding/protojson/decode.go
@@ -36,10 +36,13 @@
// If DiscardUnknown is set, unknown fields are ignored.
DiscardUnknown bool
- // Resolver is the registry used for type lookups when unmarshaling extensions
- // and processing Any. If Resolver is not set, unmarshaling will default to
- // using protoregistry.GlobalTypes.
- Resolver *protoregistry.Types
+ // Resolver is used for looking up types when unmarshaling
+ // google.protobuf.Any messages or extension fields.
+ // If nil, this defaults to using protoregistry.GlobalTypes.
+ Resolver interface {
+ protoregistry.MessageTypeResolver
+ protoregistry.ExtensionTypeResolver
+ }
decoder *json.Decoder
}
diff --git a/encoding/protojson/encode.go b/encoding/protojson/encode.go
index bd0ee3d..d789986 100644
--- a/encoding/protojson/encode.go
+++ b/encoding/protojson/encode.go
@@ -36,10 +36,11 @@
// composed of space or tab characters.
Indent string
- // Resolver is the registry used for type lookups when marshaling
- // google.protobuf.Any messages. If Resolver is not set, marshaling will
- // default to using protoregistry.GlobalTypes.
- Resolver *protoregistry.Types
+ // Resolver is used for looking up types when expanding google.protobuf.Any
+ // messages. If nil, this defaults to using protoregistry.GlobalTypes.
+ Resolver interface {
+ protoregistry.MessageTypeResolver
+ }
encoder *json.Encoder
}