encoding/protojson: add MarshalOptions.UseEnumNumbers

UseEnumNumbers=true will emit enum values as JSON numbers.

Change-Id: I6f3c814e06dc1e3dd595ad35aa79871a49718cd5
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/194017
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/encoding/protojson/encode.go b/encoding/protojson/encode.go
index c761fec..d55786e 100644
--- a/encoding/protojson/encode.go
+++ b/encoding/protojson/encode.go
@@ -34,6 +34,9 @@
 	// Marshal will return error if there are any missing required fields.
 	AllowPartial bool
 
+	// UseEnumNumbers emits enum values as numbers.
+	UseEnumNumbers bool
+
 	// EmitUnpopulated specifies whether to emit unpopulated fields. It does not
 	// emit unpopulated oneof fields or unpopulated extension fields.
 	// The JSON value emitted for unpopulated fields are as follows:
@@ -197,14 +200,16 @@
 	case pref.EnumKind:
 		if fd.Enum().FullName() == "google.protobuf.NullValue" {
 			o.encoder.WriteNull()
-		} else if desc := fd.Enum().Values().ByNumber(val.Enum()); desc != nil {
-			err := o.encoder.WriteString(string(desc.Name()))
-			if err != nil {
-				return err
-			}
 		} else {
-			// Use numeric value if there is no enum value descriptor.
-			o.encoder.WriteInt(int64(val.Enum()))
+			desc := fd.Enum().Values().ByNumber(val.Enum())
+			if o.UseEnumNumbers || desc == nil {
+				o.encoder.WriteInt(int64(val.Enum()))
+			} else {
+				err := o.encoder.WriteString(string(desc.Name()))
+				if err != nil {
+					return err
+				}
+			}
 		}
 
 	case pref.MessageKind, pref.GroupKind: