Skip to content

Commit 28dd678

Browse files
authored
Merge pull request #10 from cwalther/json2oneof
json2protobuf fails on oneof fields
2 parents ba4792f + 4cfd037 commit 28dd678

File tree

3 files changed

+222
-2
lines changed

3 files changed

+222
-2
lines changed

src/protobuf2json.c

+6-1
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,10 @@ static int json2protobuf_process_message(
743743
void *protobuf_value = ((char *)*protobuf_message) + field_descriptor->offset;
744744
void *protobuf_value_quantifier = ((char *)*protobuf_message) + field_descriptor->quantifier_offset;
745745

746+
if (field_descriptor->flags & PROTOBUF_C_FIELD_FLAG_ONEOF) {
747+
*(uint32_t*)protobuf_value_quantifier = field_descriptor->id;
748+
}
749+
746750
if (field_descriptor->label == PROTOBUF_C_LABEL_REQUIRED) {
747751
result = json2protobuf_process_field(field_descriptor, json_object_value, protobuf_value, error_string, error_size);
748752
if (result) {
@@ -751,7 +755,8 @@ static int json2protobuf_process_message(
751755
return result;
752756
}
753757
} else if (field_descriptor->label == PROTOBUF_C_LABEL_OPTIONAL) {
754-
if (field_descriptor->type == PROTOBUF_C_TYPE_MESSAGE || field_descriptor->type == PROTOBUF_C_TYPE_STRING) {
758+
if (field_descriptor->type == PROTOBUF_C_TYPE_MESSAGE || field_descriptor->type == PROTOBUF_C_TYPE_STRING
759+
|| (field_descriptor->flags & PROTOBUF_C_FIELD_FLAG_ONEOF)) {
755760
// Do nothing
756761
} else {
757762
*(protobuf_c_boolean *)protobuf_value_quantifier = 1;

test/test-list.h

+10
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ TEST_DECLARE(reversible__default_values)
6060
TEST_DECLARE(reversible__numbers)
6161
TEST_DECLARE(reversible__strings)
6262
TEST_DECLARE(reversible__bytes)
63+
TEST_DECLARE(reversible__oneof_none)
64+
TEST_DECLARE(reversible__oneof_one)
65+
TEST_DECLARE(reversible__oneof_other)
66+
TEST_DECLARE(reversible__oneof_both_first)
67+
TEST_DECLARE(reversible__oneof_both_second)
6368

6469
TASK_LIST_START
6570
TEST_ENTRY(protobuf2json_file__success)
@@ -116,4 +121,9 @@ TASK_LIST_START
116121
TEST_ENTRY(reversible__numbers)
117122
TEST_ENTRY(reversible__strings)
118123
TEST_ENTRY(reversible__bytes)
124+
TEST_ENTRY(reversible__oneof_none)
125+
TEST_ENTRY(reversible__oneof_one)
126+
TEST_ENTRY(reversible__oneof_other)
127+
TEST_ENTRY(reversible__oneof_both_first)
128+
TEST_ENTRY(reversible__oneof_both_second)
119129
TASK_LIST_END

test/test-reversible.c

+206-1
Original file line numberDiff line numberDiff line change
@@ -418,4 +418,209 @@ TEST_IMPL(reversible__bytes) {
418418
free(json_string);
419419

420420
RETURN_OK();
421-
}
421+
}
422+
423+
TEST_IMPL(reversible__oneof_none) {
424+
int result;
425+
426+
const char *initial_json_string = \
427+
"{}"
428+
;
429+
430+
ProtobufCMessage *protobuf_message;
431+
432+
result = json2protobuf_string((char *)initial_json_string, JSON_ALLOW_NUL, &foo__something__descriptor, &protobuf_message, NULL, 0);
433+
ASSERT_ZERO(result);
434+
435+
Foo__Something *something = (Foo__Something *)protobuf_message;
436+
437+
ASSERT_EQUALS(something->something_case, FOO__SOMETHING__SOMETHING__NOT_SET);
438+
ASSERT(something->oneof_string == NULL);
439+
440+
char *json_string;
441+
result = protobuf2json_string(protobuf_message, TEST_JSON_FLAGS, &json_string, NULL, 0);
442+
ASSERT_ZERO(result);
443+
ASSERT(json_string);
444+
445+
const char *expected_json_string = initial_json_string;
446+
447+
ASSERT_STRCMP(
448+
json_string,
449+
expected_json_string
450+
);
451+
452+
protobuf_c_message_free_unpacked(protobuf_message, NULL);
453+
free(json_string);
454+
455+
RETURN_OK();
456+
}
457+
458+
TEST_IMPL(reversible__oneof_one) {
459+
int result;
460+
461+
const char *initial_json_string = \
462+
"{\n"
463+
" \"oneof_string\": \"hello\"\n"
464+
"}"
465+
;
466+
467+
ProtobufCMessage *protobuf_message;
468+
469+
result = json2protobuf_string((char *)initial_json_string, JSON_ALLOW_NUL, &foo__something__descriptor, &protobuf_message, NULL, 0);
470+
ASSERT_ZERO(result);
471+
472+
Foo__Something *something = (Foo__Something *)protobuf_message;
473+
474+
ASSERT_EQUALS(something->something_case, FOO__SOMETHING__SOMETHING_ONEOF_STRING);
475+
ASSERT_STRCMP(something->oneof_string, "hello");
476+
477+
char *json_string;
478+
result = protobuf2json_string(protobuf_message, TEST_JSON_FLAGS, &json_string, NULL, 0);
479+
ASSERT_ZERO(result);
480+
ASSERT(json_string);
481+
482+
const char *expected_json_string = initial_json_string;
483+
484+
ASSERT_STRCMP(
485+
json_string,
486+
expected_json_string
487+
);
488+
489+
protobuf_c_message_free_unpacked(protobuf_message, NULL);
490+
free(json_string);
491+
492+
RETURN_OK();
493+
}
494+
495+
TEST_IMPL(reversible__oneof_other) {
496+
int result;
497+
498+
const char *initial_json_string = \
499+
"{\n"
500+
" \"oneof_bytes\": \"d29ybGQ=\"\n"
501+
"}"
502+
;
503+
504+
ProtobufCMessage *protobuf_message;
505+
506+
result = json2protobuf_string((char *)initial_json_string, JSON_ALLOW_NUL, &foo__something__descriptor, &protobuf_message, NULL, 0);
507+
ASSERT_ZERO(result);
508+
509+
Foo__Something *something = (Foo__Something *)protobuf_message;
510+
511+
ASSERT_EQUALS(something->something_case, FOO__SOMETHING__SOMETHING_ONEOF_BYTES);
512+
ASSERT_EQUALS((int)something->oneof_bytes.len, 5);
513+
ASSERT_STRCMP((const char*)something->oneof_bytes.data, "world");
514+
515+
char *json_string;
516+
result = protobuf2json_string(protobuf_message, TEST_JSON_FLAGS, &json_string, NULL, 0);
517+
ASSERT_ZERO(result);
518+
ASSERT(json_string);
519+
520+
const char *expected_json_string = initial_json_string;
521+
522+
ASSERT_STRCMP(
523+
json_string,
524+
expected_json_string
525+
);
526+
527+
protobuf_c_message_free_unpacked(protobuf_message, NULL);
528+
free(json_string);
529+
530+
RETURN_OK();
531+
}
532+
533+
TEST_IMPL(reversible__oneof_both_first) {
534+
#if JANSSON_VERSION_HEX < 0x020800
535+
RETURN_SKIP("behavior for multiple oneof values can only be guaranteed for Jansson >= 2.8");
536+
#else
537+
int result;
538+
539+
const char *initial_json_string = \
540+
"{\n"
541+
" \"oneof_string\": \"hello\",\n"
542+
" \"oneof_bytes\": \"d29ybGQ=\"\n"
543+
"}"
544+
;
545+
546+
ProtobufCMessage *protobuf_message;
547+
548+
result = json2protobuf_string((char *)initial_json_string, JSON_ALLOW_NUL, &foo__something__descriptor, &protobuf_message, NULL, 0);
549+
ASSERT_ZERO(result);
550+
551+
Foo__Something *something = (Foo__Something *)protobuf_message;
552+
553+
// last input wins, irrespective of order in proto definition
554+
ASSERT_EQUALS(something->something_case, FOO__SOMETHING__SOMETHING_ONEOF_BYTES);
555+
ASSERT_EQUALS((int)something->oneof_bytes.len, 5);
556+
ASSERT_STRCMP((const char*)something->oneof_bytes.data, "world");
557+
558+
char *json_string;
559+
result = protobuf2json_string(protobuf_message, TEST_JSON_FLAGS, &json_string, NULL, 0);
560+
ASSERT_ZERO(result);
561+
ASSERT(json_string);
562+
563+
const char *expected_json_string = \
564+
"{\n"
565+
" \"oneof_bytes\": \"d29ybGQ=\"\n"
566+
"}"
567+
;
568+
569+
ASSERT_STRCMP(
570+
json_string,
571+
expected_json_string
572+
);
573+
574+
protobuf_c_message_free_unpacked(protobuf_message, NULL);
575+
free(json_string);
576+
577+
RETURN_OK();
578+
#endif
579+
}
580+
581+
TEST_IMPL(reversible__oneof_both_second) {
582+
#if JANSSON_VERSION_HEX < 0x020800
583+
RETURN_SKIP("behavior for multiple oneof values can only be guaranteed for Jansson >= 2.8");
584+
#else
585+
int result;
586+
587+
const char *initial_json_string = \
588+
"{\n"
589+
" \"oneof_bytes\": \"d29ybGQ=\",\n"
590+
" \"oneof_string\": \"hello\"\n"
591+
"}"
592+
;
593+
594+
ProtobufCMessage *protobuf_message;
595+
596+
result = json2protobuf_string((char *)initial_json_string, JSON_ALLOW_NUL, &foo__something__descriptor, &protobuf_message, NULL, 0);
597+
ASSERT_ZERO(result);
598+
599+
Foo__Something *something = (Foo__Something *)protobuf_message;
600+
601+
// last input wins, irrespective of order in proto definition
602+
ASSERT_EQUALS(something->something_case, FOO__SOMETHING__SOMETHING_ONEOF_STRING);
603+
ASSERT_STRCMP(something->oneof_string, "hello");
604+
605+
char *json_string;
606+
result = protobuf2json_string(protobuf_message, TEST_JSON_FLAGS, &json_string, NULL, 0);
607+
ASSERT_ZERO(result);
608+
ASSERT(json_string);
609+
610+
const char *expected_json_string = \
611+
"{\n"
612+
" \"oneof_string\": \"hello\"\n"
613+
"}"
614+
;
615+
616+
ASSERT_STRCMP(
617+
json_string,
618+
expected_json_string
619+
);
620+
621+
protobuf_c_message_free_unpacked(protobuf_message, NULL);
622+
free(json_string);
623+
624+
RETURN_OK();
625+
#endif
626+
}

0 commit comments

Comments
 (0)