mirror of
https://github.com/go-kratos/kratos.git
synced 2025-01-28 03:57:02 +02:00
fix FieldMask are converted to/from lower-camel naming conventions. (#1724)
This commit is contained in:
parent
b6b95089c4
commit
11a6120a2e
@ -34,7 +34,7 @@ func (c codec) Marshal(v interface{}) ([]byte, error) {
|
||||
var vs url.Values
|
||||
var err error
|
||||
if m, ok := v.(proto.Message); ok {
|
||||
vs, err = EncodeMap(m)
|
||||
vs, err = EncodeValues(m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -66,9 +66,9 @@ func (c codec) Unmarshal(data []byte, v interface{}) error {
|
||||
rv = rv.Elem()
|
||||
}
|
||||
if m, ok := v.(proto.Message); ok {
|
||||
return MapProto(m, vs)
|
||||
return DecodeValues(m, vs)
|
||||
} else if m, ok := reflect.Indirect(reflect.ValueOf(v)).Interface().(proto.Message); ok {
|
||||
return MapProto(m, vs)
|
||||
return DecodeValues(m, vs)
|
||||
}
|
||||
|
||||
return c.decoder.Decode(v, vs)
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@ -19,7 +20,8 @@ import (
|
||||
"google.golang.org/protobuf/types/known/wrapperspb"
|
||||
)
|
||||
|
||||
func MapProto(msg proto.Message, values map[string][]string) error {
|
||||
// DecodeValues decode url value into proto message.
|
||||
func DecodeValues(msg proto.Message, values url.Values) error {
|
||||
for key, values := range values {
|
||||
if err := populateFieldValues(msg.ProtoReflect(), strings.Split(key, "."), values); err != nil {
|
||||
return err
|
||||
@ -285,7 +287,9 @@ func parseMessage(md protoreflect.MessageDescriptor, value string) (protoreflect
|
||||
msg = wrapperspb.Bytes(v)
|
||||
case "google.protobuf.FieldMask":
|
||||
fm := &field_mask.FieldMask{}
|
||||
fm.Paths = append(fm.Paths, strings.Split(value, ",")...)
|
||||
for _, fv := range strings.Split(value, ",") {
|
||||
fm.Paths = append(fm.Paths, jsonSnakeCase(fv))
|
||||
}
|
||||
msg = fm
|
||||
case "google.protobuf.Value":
|
||||
fm, err := structpb.NewValue(value)
|
||||
@ -298,3 +302,23 @@ func parseMessage(md protoreflect.MessageDescriptor, value string) (protoreflect
|
||||
}
|
||||
return protoreflect.ValueOfMessage(msg.ProtoReflect()), nil
|
||||
}
|
||||
|
||||
// jsonSnakeCase converts a camelCase identifier to a snake_case identifier,
|
||||
// according to the protobuf JSON specification.
|
||||
// references: https://github.com/protocolbuffers/protobuf-go/blob/master/encoding/protojson/well_known_types.go#L864
|
||||
func jsonSnakeCase(s string) string {
|
||||
var b []byte
|
||||
for i := 0; i < len(s); i++ { // proto identifiers are always ASCII
|
||||
c := s[i]
|
||||
if isASCIIUpper(c) {
|
||||
b = append(b, '_')
|
||||
c += 'a' - 'A' // convert to lowercase
|
||||
}
|
||||
b = append(b, c)
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func isASCIIUpper(c byte) bool {
|
||||
return 'A' <= c && c <= 'Z'
|
||||
}
|
||||
|
@ -13,8 +13,8 @@ import (
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
)
|
||||
|
||||
// EncodeMap encode proto message to url query.
|
||||
func EncodeMap(msg proto.Message) (url.Values, error) {
|
||||
// EncodeValues encode a message into url values.
|
||||
func EncodeValues(msg proto.Message) (url.Values, error) {
|
||||
if msg == nil || (reflect.ValueOf(msg).Kind() == reflect.Ptr && reflect.ValueOf(msg).IsNil()) {
|
||||
return url.Values{}, nil
|
||||
}
|
||||
@ -165,8 +165,34 @@ func encodeMessage(msgDescriptor protoreflect.MessageDescriptor, value protorefl
|
||||
if !ok {
|
||||
return "", nil
|
||||
}
|
||||
for i, v := range m.Paths {
|
||||
m.Paths[i] = jsonCamelCase(v)
|
||||
}
|
||||
return strings.Join(m.Paths, ","), nil
|
||||
default:
|
||||
return "", fmt.Errorf("unsupported message type: %q", string(msgDescriptor.FullName()))
|
||||
}
|
||||
}
|
||||
|
||||
// JSONCamelCase converts a snake_case identifier to a camelCase identifier,
|
||||
// according to the protobuf JSON specification.
|
||||
// references: https://github.com/protocolbuffers/protobuf-go/blob/master/encoding/protojson/well_known_types.go#L842
|
||||
func jsonCamelCase(s string) string {
|
||||
var b []byte
|
||||
var wasUnderscore bool
|
||||
for i := 0; i < len(s); i++ { // proto identifiers are always ASCII
|
||||
c := s[i]
|
||||
if c != '_' {
|
||||
if wasUnderscore && isASCIILower(c) {
|
||||
c -= 'a' - 'A' // convert to uppercase
|
||||
}
|
||||
b = append(b, c)
|
||||
}
|
||||
wasUnderscore = c == '_'
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func isASCIILower(c byte) bool {
|
||||
return 'a' <= c && c <= 'z'
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ func EncodeURL(pathTemplate string, msg proto.Message, needQuery bool) string {
|
||||
return in
|
||||
})
|
||||
if needQuery {
|
||||
u, err := form.EncodeMap(msg)
|
||||
u, err := form.EncodeValues(msg)
|
||||
if err == nil && len(u) > 0 {
|
||||
for key := range pathParams {
|
||||
delete(u, key)
|
||||
|
Loading…
x
Reference in New Issue
Block a user