Skip to content

Commit 4aa425c

Browse files
acozzettelfittl
andauthored
Cherry-pick #8356 into 3.16.x (#8518)
* Ruby: Add support for proto3 json_name in compiler and field definitions * Address review feedback * Add test for json_name functionality Co-authored-by: Lukas Fittl <[email protected]>
1 parent e8b78f8 commit 4aa425c

File tree

4 files changed

+50
-8
lines changed

4 files changed

+50
-8
lines changed

ruby/ext/google/protobuf_c/defs.c

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,20 @@ static VALUE FieldDescriptor_default(VALUE _self) {
868868
return Convert_UpbToRuby(default_val, TypeInfo_get(self->fielddef), Qnil);
869869
}
870870

871+
872+
/*
873+
* call-seq:
874+
* FieldDescriptor.json_name => json_name
875+
*
876+
* Returns this field's json_name, as a Ruby string, or nil if not yet set.
877+
*/
878+
static VALUE FieldDescriptor_json_name(VALUE _self) {
879+
FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
880+
const upb_fielddef *f = self->fielddef;
881+
const char *json_name = upb_fielddef_jsonname(f);
882+
return rb_str_new2(json_name);
883+
}
884+
871885
/*
872886
* call-seq:
873887
* FieldDescriptor.label => label
@@ -1043,6 +1057,7 @@ static void FieldDescriptor_register(VALUE module) {
10431057
rb_define_method(klass, "name", FieldDescriptor_name, 0);
10441058
rb_define_method(klass, "type", FieldDescriptor__type, 0);
10451059
rb_define_method(klass, "default", FieldDescriptor_default, 0);
1060+
rb_define_method(klass, "json_name", FieldDescriptor_json_name, 0);
10461061
rb_define_method(klass, "label", FieldDescriptor_label, 0);
10471062
rb_define_method(klass, "number", FieldDescriptor_number, 0);
10481063
rb_define_method(klass, "submsg_name", FieldDescriptor_submsg_name, 0);
@@ -1750,6 +1765,16 @@ static void msgdef_add_field(VALUE msgbuilder_rb, upb_label_t label, VALUE name,
17501765
field_proto,
17511766
FileBuilderContext_strdup(self->file_builder, default_value));
17521767
}
1768+
1769+
if (rb_funcall(options, rb_intern("key?"), 1,
1770+
ID2SYM(rb_intern("json_name"))) == Qtrue) {
1771+
VALUE json_name =
1772+
rb_hash_lookup(options, ID2SYM(rb_intern("json_name")));
1773+
1774+
google_protobuf_FieldDescriptorProto_set_json_name(
1775+
field_proto,
1776+
FileBuilderContext_strdup(self->file_builder, json_name));
1777+
}
17531778
}
17541779

17551780
if (oneof_index >= 0) {
@@ -1899,18 +1924,20 @@ static VALUE MessageBuilderContext_required(int argc, VALUE* argv,
18991924
*/
19001925
static VALUE MessageBuilderContext_repeated(int argc, VALUE* argv,
19011926
VALUE _self) {
1902-
VALUE name, type, number, type_class;
1927+
VALUE name, type, number;
1928+
VALUE type_class, options = Qnil;
19031929

1904-
if (argc < 3) {
1905-
rb_raise(rb_eArgError, "Expected at least 3 arguments.");
1930+
rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options);
1931+
1932+
// Allow passing (name, type, number, options) or
1933+
// (name, type, number, type_class, options)
1934+
if (argc == 4 && RB_TYPE_P(type_class, T_HASH)) {
1935+
options = type_class;
1936+
type_class = Qnil;
19061937
}
1907-
name = argv[0];
1908-
type = argv[1];
1909-
number = argv[2];
1910-
type_class = (argc > 3) ? argv[3] : Qnil;
19111938

19121939
msgdef_add_field(_self, UPB_LABEL_REPEATED, name, type, number, type_class,
1913-
Qnil, -1, false);
1940+
options, -1, false);
19141941

19151942
return Qnil;
19161943
}

ruby/tests/encode_decode_test.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,4 +95,10 @@ def test_encode_wrong_msg
9595
end
9696
end
9797

98+
def test_json_name
99+
msg = A::B::C::TestJsonName.new(:value => 42)
100+
json = msg.to_json
101+
assert_match json, "{\"CustomJsonName\":42}"
102+
end
103+
98104
end

ruby/tests/generated_code.proto

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,7 @@ message TestUnknown {
8383
map<string, TestUnknown> map_unknown = 67;
8484
int32 unknown_field = 89;
8585
}
86+
87+
message TestJsonName {
88+
int32 value = 1 [json_name = "CustomJsonName"];
89+
}

src/google/protobuf/compiler/ruby/ruby_generator.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,11 @@ void GenerateField(const FieldDescriptor* field, io::Printer* printer) {
220220
DefaultValueForField(field));
221221
}
222222

223+
if (field->has_json_name()) {
224+
printer->Print(", json_name: \"$json_name$\"", "json_name",
225+
field->json_name());
226+
}
227+
223228
printer->Print("\n");
224229
}
225230
}

0 commit comments

Comments
 (0)