Fixed to_h with repeated messages to return hashes in Ruby

This commit is contained in:
Zachary Anker 2017-09-14 08:35:13 -07:00
parent d1bc27caef
commit 83264bd160
3 changed files with 22 additions and 3 deletions

View File

@ -419,6 +419,13 @@ VALUE Message_to_h(VALUE _self) {
msg_value = Map_to_h(msg_value);
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
msg_value = RepeatedField_to_ary(msg_value);
if (upb_fieldddef_type(field) == UPB_TYPE_MESSAGE) {
for (int i = 0; i < RARRAY_LEN(msg_value); i++) {
VALUE elem = rb_ary_entry(msg_value, i);
rb_ary_store(msg_value, i, Message_to_h(elem));
}
}
} else if (msg_value != Qnil &&
upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
msg_value = Message_to_h(msg_value);

View File

@ -367,7 +367,19 @@ public class RubyMessage extends RubyObject {
for (Descriptors.FieldDescriptor fdef : this.descriptor.getFields()) {
IRubyObject value = getField(context, fdef);
if (!value.isNil()) {
if (value.respondsTo("to_h")) {
if (fdef.isRepeated() && !fdef.isMapField()) {
if (fdef.getType() != Descriptors.FieldDescriptor.Type.MESSAGE) {
value = Helpers.invoke(context, value, "to_a");
} else {
RubyArray ary = value.convertToArray();
for (int i = 0; i < ary.size(); i++) {
IRubyObject submsg = Helpers.invoke(context, ary.eltInternal(i), "to_h");
ary.eltInternalSet(i, submsg);
}
value = ary.to_ary();
}
} else if (value.respondsTo("to_h")) {
value = Helpers.invoke(context, value, "to_h");
} else if (value.respondsTo("to_a")) {
value = Helpers.invoke(context, value, "to_a");

View File

@ -927,7 +927,7 @@ module BasicTest
end
def test_to_h
m = TestMessage.new(:optional_bool => true, :optional_double => -10.100001, :optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
m = TestMessage.new(:optional_bool => true, :optional_double => -10.100001, :optional_string => 'foo', :repeated_string => ['bar1', 'bar2'], :repeated_msg => [TestMessage2.new(:foo => 100)])
expected_result = {
:optional_bool=>true,
:optional_bytes=>"",
@ -947,7 +947,7 @@ module BasicTest
:repeated_float=>[],
:repeated_int32=>[],
:repeated_int64=>[],
:repeated_msg=>[],
:repeated_msg=>[{:foo => 100}],
:repeated_string=>["bar1", "bar2"],
:repeated_uint32=>[],
:repeated_uint64=>[]