feat(6178): emit ruby enum as integer (#11673)
Fixes #6178
- Add a new option `enums_as_integers` to emit enum as integer value.
Closes #11673
COPYBARA_INTEGRATE_REVIEW=https://github.com/protocolbuffers/protobuf/pull/11673 from MQuy:feat/6178-ruby-enum-as-integer 90f986a5fd2f5e8bda3f338c67304ef96feee446
PiperOrigin-RevId: 514789180
diff --git a/ruby/ext/google/protobuf_c/message.c b/ruby/ext/google/protobuf_c/message.c
index 067a446..ab19d27 100644
--- a/ruby/ext/google/protobuf_c/message.c
+++ b/ruby/ext/google/protobuf_c/message.c
@@ -1164,6 +1164,12 @@
Qfalse))) {
options |= upb_JsonEncode_EmitDefaults;
}
+
+ if (RTEST(rb_hash_lookup2(hash_args,
+ ID2SYM(rb_intern("format_enums_as_integers")),
+ Qfalse))) {
+ options |= upb_JsonEncode_FormatEnumsAsIntegers;
+ }
}
upb_Status_Clear(&status);
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
index 92a31d6..dc76e2d 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
@@ -669,6 +669,7 @@
* @param options [Hash] options for the decoder
* preserve_proto_fieldnames: set true to use original fieldnames (default is to camelCase)
* emit_defaults: set true to emit 0/false values (default is to omit them)
+ * format_enums_as_integers: set true to emit enum values as integer (default is string)
*/
@JRubyMethod(name = "encode_json", required = 1, optional = 1, meta = true)
public static IRubyObject encodeJson(
@@ -690,6 +691,8 @@
IRubyObject emitDefaults = options.fastARef(runtime.newSymbol("emit_defaults"));
IRubyObject preserveNames = options.fastARef(runtime.newSymbol("preserve_proto_fieldnames"));
+ IRubyObject printingEnumsAsInts =
+ options.fastARef(runtime.newSymbol("format_enums_as_integers"));
if (emitDefaults != null && emitDefaults.isTrue()) {
printer = printer.includingDefaultValueFields();
@@ -698,6 +701,10 @@
if (preserveNames != null && preserveNames.isTrue()) {
printer = printer.preservingProtoFieldNames();
}
+
+ if (printingEnumsAsInts != null && printingEnumsAsInts.isTrue()) {
+ printer = printer.printingEnumsAsInts();
+ }
}
printer =
printer.usingTypeRegistry(
diff --git a/ruby/tests/encode_decode_test.rb b/ruby/tests/encode_decode_test.rb
index df2cd36..710e754 100755
--- a/ruby/tests/encode_decode_test.rb
+++ b/ruby/tests/encode_decode_test.rb
@@ -84,6 +84,34 @@
)
assert_match 'optional_int32', json
+
+
+ # Test for enums printing as ints.
+ msg = A::B::C::TestMessage.new({ optional_enum: 1 })
+ json = A::B::C::TestMessage.encode_json(
+ msg,
+ { :format_enums_as_integers => true }
+ )
+
+ assert_match '"optionalEnum":1', json
+
+ # Test for default enum being printed as int.
+ msg = A::B::C::TestMessage.new({ optional_enum: 0 })
+ json = A::B::C::TestMessage.encode_json(
+ msg,
+ { :format_enums_as_integers => true, :emit_defaults => true }
+ )
+
+ assert_match '"optionalEnum":0', json
+
+ # Test for repeated enums printing as ints.
+ msg = A::B::C::TestMessage.new({ repeated_enum: [0,1,2,3] })
+ json = A::B::C::TestMessage.encode_json(
+ msg,
+ { :format_enums_as_integers => true }
+ )
+
+ assert_match '"repeatedEnum":[0,1,2,3]', json
end
def test_encode_wrong_msg