[
https://issues.apache.org/jira/browse/AVRO-3810?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Thiruvalluvan M. G. reassigned AVRO-3810:
-----------------------------------------
Assignee: Thiruvalluvan M. G.
> Incorrect JSON generated by avro::jsonEncoder from avro::GenericDatum when
> schema contains as last value a record with 0 field
> ------------------------------------------------------------------------------------------------------------------------------
>
> Key: AVRO-3810
> URL: https://issues.apache.org/jira/browse/AVRO-3810
> Project: Apache Avro
> Issue Type: Bug
> Components: c++
> Environment: Windows, 64bit, compiled with msvc
> Reporter: Jerome Delrieu
> Assignee: Thiruvalluvan M. G.
> Priority: Major
>
> When the Schema has a record with 0 field as its last value, the
> avro::jsonEncoder doesn't generate the last characters in the JSON string.
> The obtained JSON string is malformed and cannot be parsed with a standard
> JSON parser.
> Note : the avro::{color:#74531f}jsonDecoder {color}accept this string whereas
> it is not a valid JSON syntax
> small C++ example:
> {color:#0000FF}const{color} {color:#0000FF}char{color}
> *{color:#1f377f}sSchema{color} =
> {color:#e21f1f}"{color}{color:#a31515}{{color}{color:#b776fb}\"{color}{color:#a31515}type{color}{color:#b776fb}\"{color}{color:#a31515}:
>
> {color}{color:#b776fb}\"{color}{color:#a31515}record{color}{color:#b776fb}\"{color}{color:#a31515},{color}{color:#b776fb}\"{color}{color:#a31515}name{color}{color:#b776fb}\"{color}{color:#a31515}
> :
> {color}{color:#b776fb}\"{color}{color:#a31515}Event{color}{color:#b776fb}\"{color}{color:#a31515},{color}{color:#b776fb}\"{color}{color:#a31515}namespace{color}{color:#b776fb}\"{color}{color:#a31515}
> :
> {color}{color:#b776fb}\"{color}{color:#a31515}test{color}{color:#b776fb}\"{color}{color:#a31515},{color}{color:#b776fb}\"{color}{color:#a31515}doc{color}{color:#b776fb}\"{color}{color:#a31515}
> : {color}{color:#b776fb}\"\"{color}{color:#a31515},
> {color}{color:#b776fb}\"{color}{color:#a31515}fields{color}{color:#b776fb}\"{color}{color:#a31515}
> : {color}{color:#e21f1f}"{color} {color:#e21f1f}"{color}{color:#a31515}[ {
> {color}{color:#b776fb}\"{color}{color:#a31515}name{color}{color:#b776fb}\"{color}{color:#a31515}:
>
> {color}{color:#b776fb}\"{color}{color:#a31515}Event{color}{color:#b776fb}\"{color}{color:#a31515},
>
> {color}{color:#b776fb}\"{color}{color:#a31515}type{color}{color:#b776fb}\"{color}{color:#a31515}
> : [ {
> {color}{color:#b776fb}\"{color}{color:#a31515}type{color}{color:#b776fb}\"{color}{color:#a31515}:
>
> {color}{color:#b776fb}\"{color}{color:#a31515}record{color}{color:#b776fb}\"{color}{color:#a31515},
>
> {color}{color:#b776fb}\"{color}{color:#a31515}name{color}{color:#b776fb}\"{color}{color:#a31515}
> :
> {color}{color:#b776fb}\"{color}{color:#a31515}ABEvent{color}{color:#b776fb}\"{color}{color:#a31515},
>
> {color}{color:#b776fb}\"{color}{color:#a31515}doc{color}{color:#b776fb}\"{color}{color:#a31515}
> :
> {color}{color:#b776fb}\"{color}{color:#a31515}unused{color}{color:#b776fb}\"{color}{color:#a31515},{color}{color:#e21f1f}"{color}
>
> {color:#e21f1f}"{color}{color:#b776fb}\"{color}{color:#a31515}fields{color}{color:#b776fb}\"{color}{color:#a31515}
> : [ ] } ] } ] }{color}{color:#e21f1f}"{color};
> avro::{color:#2b91af}ValidSchema{color}
> {color:#1f377f}schema{color}(avro::{color:#74531f}compileJsonSchemaFromString{color}({color:#1f377f}sSchema{color}));
> avro::{color:#2b91af}GenericDatum{color}
> {color:#1f377f}datumDecode{color}({color:#1f377f}schema{color});
> avro::{color:#2b91af}DecoderPtr{color} {color:#1f377f}decoder{color} =
> avro::{color:#74531f}binaryDecoder{color}();
> {color:#008000}// only one byte, 0, as source for decoding{color}
> {color:#2b91af}uint8_t{color} {color:#1f377f}binarySource{color} = 0;
> std::{color:#2b91af}unique_ptr{color}<avro::{color:#2b91af}InputStream{color}>
> {color:#1f377f}in{color} =
> avro::{color:#74531f}memoryInputStream{color}(({color:#2b91af}uint8_t{color}
> *)&{color:#1f377f}binarySource{color}, 1);
> {color:#1f377f}decoder{color}{color:#008080}->{color}{color:#74531f}init{color}({color:#008080}*{color}{color:#1f377f}in{color});
>
> avro::{color:#74531f}decode{color}({color:#008080}*{color}{color:#1f377f}decoder{color},
> {color:#1f377f}datumDecode{color});
> std::{color:#2b91af}unique_ptr{color}<avro::{color:#2b91af}OutputStream{color}>
> {color:#1f377f}out{color} = avro::{color:#74531f}memoryOutputStream{color}();
> std::{color:#2b91af}shared_ptr{color}<avro::{color:#2b91af}Encoder{color}>
> {color:#1f377f}encoder{color} =
> avro::{color:#74531f}jsonEncoder{color}({color:#1f377f}schema{color});
> {color:#1f377f}encoder{color}{color:#008080}->{color}{color:#74531f}init{color}({color:#008080}*{color}{color:#1f377f}out{color});
>
> avro::{color:#74531f}encode{color}({color:#008080}*{color}{color:#1f377f}encoder{color},
> {color:#1f377f}datumDecode{color});
> {color:#1f377f}encoder{color}{color:#008080}->{color}{color:#74531f}flush{color}();
> {color:#0000FF}const{color}
> std::{color:#2b91af}shared_ptr{color}<std::{color:#2b91af}vector{color}<{color:#2b91af}uint8_t{color}>
> > &{color:#1f377f}buffer{color} =
> avro::{color:#74531f}snapshot{color}(*{color:#1f377f}out{color}.{color:#74531f}get{color}());
> std::{color:#2b91af}string{color}
> {color:#1f377f}result{color}({color:#0000FF}reinterpret_cast{color}<{color:#0000FF}char{color}
>
> *>({color:#1f377f}buffer{color}.{color:#74531f}get{color}()->{color:#74531f}data{color}()),
>
> {color:#1f377f}buffer{color}.{color:#74531f}get{color}()->{color:#74531f}size{color}());
>
> Example Schema:
> Schema:
> {
> "type": "record",
> "name": "Event",
> "namespace": "test",
> "doc": "",
> "fields": [
> {
> "name": "Event",
> "type": [
> {
> "type": "record",
> "name": "ABEvent",
> "doc": "unused",
> "fields": [
>
> ]
> }
> ]
> }
> ]
> }
>
> Binary source : 1 byte 00
> Result:
> {"Event":{"test.ABEvent":
>
>
> A small patch to lang\c++\impl\parsing\Symbol.hh can solve this issue
> Before:
> void processImplicitActions() {
> for (;;) {
> Symbol &s = parsingStack.top();
> if (s.isImplicitAction()) {
> handler_.handle(s);
> parsingStack.pop();
> } else if (s.kind() == Symbol::Kind::SkipStart) {
> parsingStack.pop();
> skip(*decoder_);
> } else {
> break;
> }
> }
> }
> After:
> void processImplicitActions() {
> for (;;) {
> Symbol &s = parsingStack.top();
> if (s.isImplicitAction()) {
> handler_.handle(s);
> parsingStack.pop();
> } else if (s.kind() == Symbol::Kind::SkipStart) {
> parsingStack.pop();
> skip(*decoder_);
> } else if (s.kind() == Symbol::Kind::Indirect) {
> parsingStack.pop();
> parsingStack.push(Symbol::recordEndSymbol());
> parsingStack.push(Symbol::recordStartSymbol());
> } else {
> break;
> }
> }
> }
>
>
>
--
This message was sent by Atlassian Jira
(v8.20.10#820010)