@@ -6,6 +6,7 @@ package protojson
6
6
7
7
import (
8
8
"encoding/base64"
9
+ "encoding/hex"
9
10
"fmt"
10
11
"math"
11
12
"strconv"
@@ -41,6 +42,10 @@ type UnmarshalOptions struct {
41
42
// If DiscardUnknown is set, unknown fields and enum name values are ignored.
42
43
DiscardUnknown bool
43
44
45
+ // If UseHexForBytes is set, bytes fields are un-marshaled as hex
46
+ // strings instead of base64.
47
+ UseHexForBytes bool
48
+
44
49
// Resolver is used for looking up types when unmarshaling
45
50
// google.protobuf.Any messages or extension fields.
46
51
// If nil, this defaults to using protoregistry.GlobalTypes.
@@ -338,8 +343,14 @@ func (d decoder) unmarshalScalar(fd protoreflect.FieldDescriptor) (protoreflect.
338
343
}
339
344
340
345
case protoreflect .BytesKind :
341
- if v , ok := unmarshalBytes (tok ); ok {
342
- return v , nil
346
+ if d .opts .UseHexForBytes {
347
+ if v , ok := unmarshalBytesFromHex (tok ); ok {
348
+ return v , nil
349
+ }
350
+ } else {
351
+ if v , ok := unmarshalBytes (tok ); ok {
352
+ return v , nil
353
+ }
343
354
}
344
355
345
356
case protoreflect .EnumKind :
@@ -488,6 +499,19 @@ func unmarshalBytes(tok json.Token) (protoreflect.Value, bool) {
488
499
return protoreflect .ValueOfBytes (b ), true
489
500
}
490
501
502
+ func unmarshalBytesFromHex (tok json.Token ) (protoreflect.Value , bool ) {
503
+ if tok .Kind () != json .String {
504
+ return protoreflect.Value {}, false
505
+ }
506
+
507
+ s := tok .ParsedString ()
508
+ b , err := hex .DecodeString (s )
509
+ if err != nil {
510
+ return protoreflect.Value {}, false
511
+ }
512
+ return protoreflect .ValueOfBytes (b ), true
513
+ }
514
+
491
515
func unmarshalEnum (tok json.Token , fd protoreflect.FieldDescriptor , discardUnknown bool ) (protoreflect.Value , bool ) {
492
516
switch tok .Kind () {
493
517
case json .String :
0 commit comments