Description
What language does this apply to?
Ruby
Describe the problem you are trying to solve.
The Ruby Hash a Message object creates sometimes includes values for fields that are not applicable, specifically fields that are not set as part of the oneof
.
Describe the solution you'd like
The Ruby Hash a Message object creates does not include any field that is set to the default value.
Describe alternatives you've considered
The Ruby Hash a Message object creates excludes values for oneof
fields that are not set.
Additional context
The Ruby Hash produced by Message#to_h
sometimes contain fields of a oneof
that are not currently set, or were reset to their default value. Currently, if a oneof
value is changed from one field to another, the previous field (with it's default value) will be in the hash along with the new field (and the set value). This makes it difficult to recreate the Message object from the hash. Ideally, the Message should be able to round-trip to/from a Ruby Hash just as it can round-trip to/from a binary proto stream and to/from JSON.
The ruby/tests/basic_proto2.rb
file has the following test:
def test_to_h
m = TestMessage.new(:optional_bool => true, :optional_double => -10.100001, :optional_string => 'foo', :repeated_string => ['bar1', 'bar2'])
expected_result = {
:optional_bool=>true,
:optional_double=>-10.100001,
:optional_string=>"foo",
:repeated_string=>["bar1", "bar2"],
}
assert_equal expected_result, m.to_h
m = OneofMessage.new(:a => "foo")
expected_result = {:a => "foo"}
assert_equal expected_result, m.to_h
end
This test can be updated with the following code to demonstrate the problematic behavior:
# oneof is not set
m = OneofMessage.new
assert_equal "", m.a
assert_equal 0, m.b
assert_nil m.my_oneof
expected_result = {}
assert_equal expected_result, m.to_h
# oneof is updated to a
m.a = "foo"
assert_equal "foo", m.a
assert_equal 0, m.b
assert_equal :a, m.my_oneof
expected_result = {:a => "foo"}
assert_equal expected_result, m.to_h
# oneof is updated to b
m.b = 42
assert_equal "", m.a
assert_equal 42, m.b
assert_equal :b, m.my_oneof
expected_result = {:b => 42}
assert_equal expected_result, m.to_h # actual is {:a=>"", :b=>42}
# create new message object, using incorrect hash
m = OneofMessage.new({:a=>"foo", :b=>0})
assert_equal :a, m.my_oneof # actual is :b
expected_result = {:a => "foo"}
assert_equal expected_result, m.to_h # actual is {:a=>"foo", :b=>0}
Additionally, I think it might be a good idea if the Ruby Hash objects simply omitted any field that was set to it's default value. I believe that would correct this issue and the Ruby Hash would be more concise.
Activity