Skip to content

Commit 00cb0c5

Browse files
authored
Support java keywords as class names for records during generic deserialization codgen (#577)
1 parent 412d569 commit 00cb0c5

File tree

2 files changed

+48
-3
lines changed

2 files changed

+48
-3
lines changed

fastserde/avro-fastserde-tests-common/src/test/java/com/linkedin/avro/fastserde/FastGenericDeserializerGeneratorTest.java

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1754,6 +1754,50 @@ record = new GenericData.Record(recordWithUnionMapSchema);
17541754
Assert.assertEquals(((Map<Utf8,Integer>) recordB.get("someInts")).get(new Utf8("3")), Integer.valueOf(3));
17551755
}
17561756

1757+
@Test(groups = {"deserializationTest"}, dataProvider = "Implementation")
1758+
public void shouldHandleJavaKeywordsAsRecordNames(Implementation implementation) {
1759+
// Create schemas with Java keywords as names
1760+
Schema classSchema = createRecord("class",
1761+
createField("value", Schema.create(Schema.Type.STRING)));
1762+
1763+
Schema ifSchema = createRecord("if",
1764+
createField("value", Schema.create(Schema.Type.STRING)));
1765+
1766+
Schema publicSchema = createRecord("public",
1767+
createField("value", Schema.create(Schema.Type.STRING)));
1768+
1769+
// Create a parent record that contains records with Java keyword names
1770+
Schema parentSchema = createRecord("ParentRecord",
1771+
createField("class_field", classSchema),
1772+
createField("if_field", ifSchema),
1773+
createField("public_field", publicSchema));
1774+
1775+
// Create record instances
1776+
GenericRecord classRecord = new GenericData.Record(classSchema);
1777+
classRecord.put("value", "class value");
1778+
1779+
GenericRecord ifRecord = new GenericData.Record(ifSchema);
1780+
ifRecord.put("value", "if value");
1781+
1782+
GenericRecord publicRecord = new GenericData.Record(publicSchema);
1783+
publicRecord.put("value", "public value");
1784+
1785+
GenericRecord parentRecord = new GenericData.Record(parentSchema);
1786+
parentRecord.put("class_field", classRecord);
1787+
parentRecord.put("if_field", ifRecord);
1788+
parentRecord.put("public_field", publicRecord);
1789+
1790+
1791+
// when
1792+
GenericRecord deserializedRecord = implementation.decode(parentSchema, parentSchema,
1793+
genericDataAsDecoder(parentRecord));
1794+
1795+
// then
1796+
Assert.assertEquals(((GenericRecord)deserializedRecord.get("class_field")).get("value"), new Utf8("class value"));
1797+
Assert.assertEquals(((GenericRecord)deserializedRecord.get("if_field")).get("value"), new Utf8("if value"));
1798+
Assert.assertEquals(((GenericRecord)deserializedRecord.get("public_field")).get("value"), new Utf8("public value"));
1799+
}
1800+
17571801
@Test(groups = {"deserializationTest"}, dataProvider = "Implementation")
17581802
public void shouldBidirectionallyReadMapWithUnionMapOfUnionValues(Implementation implementation) {
17591803
// given

fastserde/avro-fastserde/src/main/java/com/linkedin/avro/fastserde/FastDeserializerGenerator.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -330,9 +330,10 @@ private void processRecord(JVar recordSchemaVar, String recordName, final Schema
330330

331331
final JVar result;
332332
JClass recordClass = null;
333+
String uniqueRecordName = getUniqueName(recordName);
333334
if (recordAction.getShouldRead()) {
334335
recordClass = schemaAssistant.classFromSchema(effectiveRecordReaderSchema);
335-
result = methodBody.decl(recordClass, recordName);
336+
result = methodBody.decl(recordClass, uniqueRecordName);
336337

337338
JExpression reuseVar = JExpr.direct(VAR_NAME_FOR_REUSE);
338339
JClass indexedRecordClass = codeModel.ref(IndexedRecord.class);
@@ -378,15 +379,15 @@ private void processRecord(JVar recordSchemaVar, String recordName, final Schema
378379

379380
popMethod._throws(IOException.class);
380381
if (recordAction.getShouldRead()) {
381-
popMethod.param(recordClass, recordName);
382+
popMethod.param(recordClass, uniqueRecordName);
382383
}
383384
popMethod.param(codeModel.ref(DatumReaderCustomization.class), VAR_NAME_FOR_CUSTOMIZATION);
384385
popMethod.param(Decoder.class, DECODER);
385386
popMethodBody = popMethod.body();
386387

387388
JInvocation invocation = methodBody.invoke(popMethod);
388389
if (recordAction.getShouldRead()) {
389-
invocation.arg(JExpr.direct(recordName));
390+
invocation.arg(JExpr.direct(uniqueRecordName));
390391
}
391392
// even if recordAction.getShouldRead() == false we need to generate 'customization' argument for javac purposes
392393
invocation.arg(customizationSupplier.get());

0 commit comments

Comments
 (0)