Skip to content

Commit badada3

Browse files
committed
AVRO-4135: [C] full type name for json encoded unions
Like java use the full type name when encoding the types for unions. This to prevent ambiguities when decoding this json encoded field back to avro using for example the java library.
1 parent 7da3211 commit badada3

File tree

3 files changed

+129
-2
lines changed

3 files changed

+129
-2
lines changed

lang/c/src/value-json.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,10 +337,12 @@ avro_value_to_json_t(const avro_value_t *value)
337337
case AVRO_UNION:
338338
{
339339
int disc;
340-
avro_value_t branch;
340+
avro_value_t branch;
341341
avro_schema_t union_schema;
342342
avro_schema_t branch_schema;
343-
const char *branch_name;
343+
const char *branch_name;
344+
const char *namespace;
345+
json_t *full_name_buf = NULL;
344346

345347
check_return(NULL, avro_value_get_current_branch(value, &branch));
346348

@@ -352,26 +354,40 @@ avro_value_to_json_t(const avro_value_t *value)
352354
union_schema = avro_value_get_schema(value);
353355
branch_schema =
354356
avro_schema_union_branch(union_schema, disc);
357+
358+
namespace = avro_schema_namespace(branch_schema);
355359
branch_name = avro_schema_type_name(branch_schema);
360+
if (namespace != NULL) {
361+
full_name_buf = json_sprintf("%s.%s", namespace, branch_name);
362+
if (full_name_buf == NULL) {
363+
avro_set_error("Cannot allocate full name union");
364+
return NULL;
365+
}
366+
branch_name = json_string_value(full_name_buf);
367+
}
356368

357369
json_t *result = json_object();
358370
if (result == NULL) {
359371
avro_set_error("Cannot allocate JSON union");
372+
json_decref(full_name_buf);
360373
return NULL;
361374
}
362375

363376
json_t *branch_json = avro_value_to_json_t(&branch);
364377
if (branch_json == NULL) {
365378
json_decref(result);
379+
json_decref(full_name_buf);
366380
return NULL;
367381
}
368382

369383
if (json_object_set_new(result, branch_name, branch_json)) {
370384
avro_set_error("Cannot append branch to union");
371385
json_decref(result);
386+
json_decref(full_name_buf);
372387
return NULL;
373388
}
374389

390+
json_decref(full_name_buf);
375391
return result;
376392
}
377393

lang/c/tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,4 @@ add_avro_test_checkmem(test_avro_1379)
8787
add_avro_test_checkmem(test_avro_1691)
8888
add_avro_test_checkmem(test_avro_1906)
8989
add_avro_test_checkmem(test_avro_1904)
90+
add_avro_test_checkmem(test_avro_4135)

lang/c/tests/test_avro_4135.c

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to you under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* https://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14+
* implied. See the License for the specific language governing
15+
* permissions and limitations under the License.
16+
*/
17+
18+
#include <stdio.h>
19+
#include <string.h>
20+
#include <avro.h>
21+
22+
#define check_exit(call) \
23+
do { \
24+
int __rc = call; \
25+
if (__rc != 0) { \
26+
fprintf(stderr, "Unexpected error:\n %s\n %s\n", \
27+
avro_strerror(), #call); \
28+
exit(EXIT_FAILURE); \
29+
} \
30+
} while (0)
31+
32+
void check_json_encoding(const avro_value_t * val, const char * expected) {
33+
char * actual;
34+
35+
check_exit(avro_value_to_json(val, 1, &actual));
36+
if (strcmp(expected, actual) != 0) {
37+
fprintf(stderr, "json encoding mismatch\n expected: %s\n actual: %s\n", expected, actual);
38+
exit(EXIT_FAILURE);
39+
}
40+
free(actual);
41+
}
42+
43+
int main(int argc, char **argv)
44+
{
45+
const char *json =
46+
"{"
47+
" \"type\": \"record\","
48+
" \"name\": \"r\","
49+
" \"fields\": ["
50+
" { \"name\": \"field\", \"type\": ["
51+
" \"null\","
52+
" \"int\","
53+
" {"
54+
" \"type\": \"record\","
55+
" \"name\": \"r1\","
56+
" \"fields\": []"
57+
" },"
58+
" {"
59+
" \"type\": \"record\","
60+
" \"name\": \"r2\","
61+
" \"namespace\": \"space\","
62+
" \"fields\": []"
63+
" }"
64+
" ]}"
65+
" ]"
66+
"}";
67+
68+
avro_schema_t schema = NULL;
69+
avro_schema_error_t error;
70+
71+
(void) argc;
72+
(void) argv;
73+
74+
check_exit(avro_schema_from_json(json, strlen(json), &schema, &error));
75+
76+
avro_value_iface_t *iface = avro_generic_class_from_schema(schema);
77+
avro_value_t val;
78+
check_exit(avro_generic_value_new(iface, &val));
79+
80+
#define TEST_AVRO_4135 (1)
81+
#if TEST_AVRO_4135
82+
{
83+
avro_value_t field;
84+
avro_value_t branch;
85+
char *json_encoding;
86+
87+
avro_value_get_by_index(&val, 0, &field, NULL);
88+
check_exit(avro_value_set_branch(&field, 0, &branch));
89+
avro_value_set_null(&branch);
90+
check_json_encoding(&val, "{\"field\": null}");
91+
92+
check_exit(avro_value_set_branch(&field, 1, &branch));
93+
avro_value_set_int(&branch, 42);
94+
check_exit(avro_value_to_json(&val, 1, &json_encoding));
95+
check_json_encoding(&val, "{\"field\": {\"int\": 42}}");
96+
97+
check_exit(avro_value_set_branch(&field, 2, &branch));
98+
check_exit(avro_value_to_json(&val, 1, &json_encoding));
99+
check_json_encoding(&val, "{\"field\": {\"r1\": {}}}");
100+
101+
check_exit(avro_value_set_branch(&field, 3, &branch));
102+
check_exit(avro_value_to_json(&val, 3, &json_encoding));
103+
check_json_encoding(&val, "{\"field\": {\"space.r2\": {}}}");
104+
}
105+
#endif
106+
107+
avro_value_decref(&val);
108+
avro_schema_decref(schema);
109+
return 0;
110+
}

0 commit comments

Comments
 (0)