Skip to content

Commit 41af1d5

Browse files
anandoleecopybara-github
authored andcommitted
loosen upb for json name conflict check in proto2 between json name and field
name. Once editions is supported this check should turn into a check on LEGACY_BEST_EFFORT PiperOrigin-RevId: 572041162
1 parent c120126 commit 41af1d5

File tree

7 files changed

+92
-22
lines changed

7 files changed

+92
-22
lines changed

python/google/protobuf/internal/json_format_test.py

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,22 @@
1212
import json
1313
import math
1414
import struct
15-
1615
import unittest
1716

17+
from google.protobuf import descriptor_pool
18+
from google.protobuf import json_format
19+
from google.protobuf.internal import more_messages_pb2
20+
from google.protobuf.internal import test_proto3_optional_pb2
21+
1822
from google.protobuf import any_pb2
1923
from google.protobuf import duration_pb2
2024
from google.protobuf import field_mask_pb2
2125
from google.protobuf import struct_pb2
2226
from google.protobuf import timestamp_pb2
2327
from google.protobuf import wrappers_pb2
24-
from google.protobuf.internal import test_proto3_optional_pb2
25-
from google.protobuf import descriptor_pool
26-
from google.protobuf import json_format
2728
from google.protobuf import any_test_pb2
28-
from google.protobuf import unittest_pb2
2929
from google.protobuf import unittest_mset_pb2
30+
from google.protobuf import unittest_pb2
3031
from google.protobuf.util import json_format_pb2
3132
from google.protobuf.util import json_format_proto3_pb2
3233

@@ -1275,5 +1276,38 @@ def testNestedRecursiveLimit(self):
12751276
json_format.Parse('{"payload": {}, "child": {"child":{}}}',
12761277
message, max_recursion_depth=3)
12771278

1279+
def testJsonNameConflictSerilize(self):
1280+
message = more_messages_pb2.ConflictJsonName(value=2)
1281+
self.assertEqual(
1282+
json.loads('{"old_value": 2}'),
1283+
json.loads(json_format.MessageToJson(message))
1284+
)
1285+
1286+
new_message = more_messages_pb2.ConflictJsonName(new_value=2)
1287+
self.assertEqual(
1288+
json.loads('{"value": 2}'),
1289+
json.loads(json_format.MessageToJson(new_message))
1290+
)
1291+
1292+
def testJsonNameConflictParse(self):
1293+
message = more_messages_pb2.ConflictJsonName()
1294+
json_format.Parse('{"value": 2}', message)
1295+
self.assertEqual(2, message.new_value)
1296+
self.assertEqual(0, message.value)
1297+
1298+
def testJsonNameConflictRoundTrip(self):
1299+
message = more_messages_pb2.ConflictJsonName(value=2)
1300+
parsed_message = more_messages_pb2.ConflictJsonName()
1301+
json_string = json_format.MessageToJson(message)
1302+
json_format.Parse(json_string, parsed_message)
1303+
self.assertEqual(message, parsed_message)
1304+
1305+
new_message = more_messages_pb2.ConflictJsonName(new_value=2)
1306+
new_parsed_message = more_messages_pb2.ConflictJsonName()
1307+
json_string = json_format.MessageToJson(new_message)
1308+
json_format.Parse(json_string, new_parsed_message)
1309+
self.assertEqual(new_message, new_parsed_message)
1310+
1311+
12781312
if __name__ == '__main__':
12791313
unittest.main()

python/google/protobuf/internal/more_messages.proto

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,3 +343,8 @@ message RequiredField {
343343
message RequiredWrapper {
344344
optional RequiredField request = 1;
345345
}
346+
347+
message ConflictJsonName {
348+
optional int32 value = 1 [json_name = "old_value"];
349+
optional int32 new_value = 2 [json_name = "value"];
350+
}

upb/json/decode_test.cc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,11 @@ TEST(JsonTest, DecodeFloats) {
9292
EXPECT_EQ(box, nullptr);
9393
}
9494
}
95+
96+
TEST(JsonTest, DecodeConflictJsonName) {
97+
upb::Arena a;
98+
std::string json_string = R"({"value": 2})";
99+
upb_test_Box* box = JsonDecode(json_string.c_str(), a.ptr());
100+
EXPECT_EQ(2, upb_test_Box_new_value(box));
101+
EXPECT_EQ(0, upb_test_Box_value(box));
102+
}

upb/json/encode_test.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,14 @@ TEST(JsonTest, EncodeNullEnum) {
103103
EXPECT_EQ(R"({"val":null})",
104104
JsonEncode(foo, upb_JsonEncode_FormatEnumsAsIntegers));
105105
}
106+
107+
TEST(JsonTest, EncodeConflictJsonName) {
108+
upb::Arena a;
109+
upb_test_Box* box = upb_test_Box_new(a.ptr());
110+
upb_test_Box_set_value(box, 2);
111+
EXPECT_EQ(R"({"old_value":2})", JsonEncode(box, 0));
112+
113+
upb_test_Box* new_box = upb_test_Box_new(a.ptr());
114+
upb_test_Box_set_new_value(new_box, 2);
115+
EXPECT_EQ(R"({"value":2})", JsonEncode(new_box, 0));
116+
}

upb/json/test.proto

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,6 @@ message Box {
4949
optional google.protobuf.Value val = 6;
5050
optional float f = 7;
5151
optional double d = 8;
52+
optional int32 value = 9 [json_name = "old_value"];
53+
optional int32 new_value = 10 [json_name = "value"];
5254
}

upb/reflection/def_type.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ typedef enum {
2727
// Only inside message table.
2828
UPB_DEFTYPE_FIELD = 0,
2929
UPB_DEFTYPE_ONEOF = 1,
30-
UPB_DEFTYPE_FIELD_JSONNAME = 2,
3130
} upb_deftype_t;
3231

3332
#ifdef __cplusplus

upb/reflection/message_def.c

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ struct upb_MessageDef {
3838
upb_inttable itof;
3939
upb_strtable ntof;
4040

41+
// Looking up fields by json name.
42+
upb_strtable jtof;
43+
4144
/* All nested defs.
4245
* MEM: We could save some space here by putting nested defs in a contiguous
4346
* region and calculating counts from offsets or vice-versa. */
@@ -63,9 +66,6 @@ struct upb_MessageDef {
6366
bool in_message_set;
6467
bool is_sorted;
6568
upb_WellKnown well_known_type;
66-
#if UINTPTR_MAX == 0xffffffff
67-
uint32_t padding; // Increase size to a multiple of 8.
68-
#endif
6969
};
7070

7171
static void assign_msg_wellknowntype(upb_MessageDef* m) {
@@ -208,16 +208,16 @@ bool upb_MessageDef_FindByNameWithSize(const upb_MessageDef* m,
208208
const upb_FieldDef* upb_MessageDef_FindByJsonNameWithSize(
209209
const upb_MessageDef* m, const char* name, size_t size) {
210210
upb_value val;
211-
const upb_FieldDef* f;
211+
212+
if (upb_strtable_lookup2(&m->jtof, name, size, &val)) {
213+
return upb_value_getconstptr(val);
214+
}
212215

213216
if (!upb_strtable_lookup2(&m->ntof, name, size, &val)) {
214217
return NULL;
215218
}
216219

217-
f = _upb_DefType_Unpack(val, UPB_DEFTYPE_FIELD);
218-
if (!f) f = _upb_DefType_Unpack(val, UPB_DEFTYPE_FIELD_JSONNAME);
219-
220-
return f;
220+
return _upb_DefType_Unpack(val, UPB_DEFTYPE_FIELD);
221221
}
222222

223223
int upb_MessageDef_ExtensionRangeCount(const upb_MessageDef* m) {
@@ -397,17 +397,25 @@ void _upb_MessageDef_InsertField(upb_DefBuilder* ctx, upb_MessageDef* m,
397397
_upb_MessageDef_Insert(m, shortname, shortnamelen, field_v, ctx->arena);
398398
if (!ok) _upb_DefBuilder_OomErr(ctx);
399399

400-
if (strcmp(shortname, json_name) != 0) {
401-
if (upb_strtable_lookup(&m->ntof, json_name, &v)) {
402-
_upb_DefBuilder_Errf(ctx, "duplicate json_name (%s)", json_name);
403-
}
400+
// TODO: Once editions is supported this should turn into a
401+
// check on LEGACY_BEST_EFFORT
402+
if (strcmp(shortname, json_name) != 0 &&
403+
upb_FileDef_Syntax(m->file) == kUpb_Syntax_Proto3 &&
404+
upb_strtable_lookup(&m->ntof, json_name, &v)) {
405+
_upb_DefBuilder_Errf(
406+
ctx, "duplicate json_name for (%s) with original field name (%s)",
407+
shortname, json_name);
408+
}
404409

405-
const size_t json_size = strlen(json_name);
406-
const upb_value json_v = _upb_DefType_Pack(f, UPB_DEFTYPE_FIELD_JSONNAME);
407-
ok = _upb_MessageDef_Insert(m, json_name, json_size, json_v, ctx->arena);
408-
if (!ok) _upb_DefBuilder_OomErr(ctx);
410+
if (upb_strtable_lookup(&m->jtof, json_name, &v)) {
411+
_upb_DefBuilder_Errf(ctx, "duplicate json_name (%s)", json_name);
409412
}
410413

414+
const size_t json_size = strlen(json_name);
415+
ok = upb_strtable_insert(&m->jtof, json_name, json_size,
416+
upb_value_constptr(f), ctx->arena);
417+
if (!ok) _upb_DefBuilder_OomErr(ctx);
418+
411419
if (upb_inttable_lookup(&m->itof, field_number, NULL)) {
412420
_upb_DefBuilder_Errf(ctx, "duplicate field number (%u)", field_number);
413421
}
@@ -660,6 +668,9 @@ static void create_msgdef(upb_DefBuilder* ctx, const char* prefix,
660668
ok = upb_strtable_init(&m->ntof, n_oneof + n_field, ctx->arena);
661669
if (!ok) _upb_DefBuilder_OomErr(ctx);
662670

671+
ok = upb_strtable_init(&m->jtof, n_field, ctx->arena);
672+
if (!ok) _upb_DefBuilder_OomErr(ctx);
673+
663674
UPB_DEF_SET_OPTIONS(m->opts, DescriptorProto, MessageOptions, msg_proto);
664675

665676
m->oneof_count = n_oneof;

0 commit comments

Comments
 (0)