Description
Csharp specific reader fails when csharp language keyword is present in namespace and datatype for on one of the element is array of complex type.
Steps to reproduce - Use following schema file to generate avro csharp classes using Apache.Avro.Tools tool (v 1.10.0)
{ "name": "Parent", "type": "record", "namespace": "com.parent.event", "fields": [ { "name": "children", "type": { "type": "array", "items": { "name": "Child", "type": "record", "fields": [ { "name": "name", "type": "string" } ] } } } ] }
Following classes will be generated. I have added link to files as content is relatively large.
https://github.com/vkhose/testcode/blob/master/com/parent/event/Parent.cs
https://github.com/vkhose/testcode/blob/master/com/parent/event/Child.cs
Please note that Avro generator tool adds an escape character "@" in namespace as event is a csharp keyword
e.g. namespace com.parent.@event
Next, I have created a test case which tries to deserialize the Parent class object
https://github.com/vkhose/testcode/blob/master/testCaseToReproduceError.cs
[Test] public void TestNamespaceWithCSharpKeyword() { var srcRecord = new Parent { children = new List<Child> { new Child { name = "test" }, new Child { name = "test" } } }; var stream = serialize(Parent._SCHEMA, srcRecord); var dstRecord = deserialize<Parent>(stream, Parent._SCHEMA, Parent._SCHEMA); Assert.NotNull(dstRecord); } }
This test case throws following exception
Unable to find type 'com.parent.@event.Child' in all loaded assemblies in field children
----> Avro.AvroException : Unable to find type 'com.parent.@event.Child' in all loaded assemblies
at Avro.Specific.SpecificDefaultReader.ReadRecord(Object reuse, RecordSchema writerSchema, Schema readerSchema, Decoder dec)
When I debug the code it seems like same util methods are used to generate code for specific record and read record during deserialization.
https://github.com/apache/avro/blob/c0094b5bb1abb79304ce42a56cc115186370d407/lang/csharp/src/apache/main/CodeGen/CodeGenUtil.cs#L99
if (ReservedKeywords.Contains(names[i]))
builder.Append(At);
Appending At(@) while generating code is correct but it should not appended while deserializing. Deserialization fails as c# reflection does not expects At(@) in string value provided to create class instance.
https://github.com/apache/avro/blob/master/lang/csharp/src/apache/main/Specific/ObjectCreator.cs#L165
Type.GetType(string) string parameter passed should be without "@" character in namespace name.
It works if I modify code not to add "@" in CodeGenUtil.cs. I think we need a fix where "@" is only added while auto generating classes and should not be used during deserialization.
Thanks.
Vaibhav
Attachments
Issue Links
- duplicates
-
AVRO-3075 Avro.AvroException namespaces with reserved words cause deserialisation issue when inside an array.
- Resolved