You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by cu...@apache.org on 2020/04/02 22:31:23 UTC

[avro] branch master updated: AVRO-2788: Default Proto repeated fields to empty arrays (#850)

This is an automated email from the ASF dual-hosted git repository.

cutting pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/avro.git


The following commit(s) were added to refs/heads/master by this push:
     new c81ea58  AVRO-2788: Default Proto repeated fields to empty arrays (#850)
c81ea58 is described below

commit c81ea58c601a2f600d9d45cf50b9f6434b911d5a
Author: Tianyu Lang <ti...@gmail.com>
AuthorDate: Thu Apr 2 15:31:14 2020 -0700

    AVRO-2788: Default Proto repeated fields to empty arrays (#850)
    
    Currently Avro<->Proto schema conversion could break compatibility
    This PR fixes the issue by assigning empty arrays as default value
    For more details, see the Jira at https://issues.apache.org/jira/browse/AVRO-2788
    
    Co-authored-by: Tianyu Lang <ti...@squareup.com>
---
 .../org/apache/avro/protobuf/ProtobufData.java     |  5 ++++-
 .../org/apache/avro/protobuf/TestProtobuf.java     | 24 +++++++++++++++++++++-
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/lang/java/protobuf/src/main/java/org/apache/avro/protobuf/ProtobufData.java b/lang/java/protobuf/src/main/java/org/apache/avro/protobuf/ProtobufData.java
index 724caf7..9b5737a 100644
--- a/lang/java/protobuf/src/main/java/org/apache/avro/protobuf/ProtobufData.java
+++ b/lang/java/protobuf/src/main/java/org/apache/avro/protobuf/ProtobufData.java
@@ -327,9 +327,12 @@ public class ProtobufData extends GenericData {
   private static final JsonNodeFactory NODES = JsonNodeFactory.instance;
 
   private JsonNode getDefault(FieldDescriptor f) {
-    if (f.isRequired() || f.isRepeated()) // no default
+    if (f.isRequired()) // no default
       return null;
 
+    if (f.isRepeated()) // empty array as repeated fields' default value
+      return NODES.arrayNode();
+
     if (f.hasDefaultValue()) { // parse spec'd default value
       Object value = f.getDefaultValue();
       switch (f.getType()) {
diff --git a/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/TestProtobuf.java b/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/TestProtobuf.java
index c7ce2d5..8536f6a 100644
--- a/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/TestProtobuf.java
+++ b/lang/java/protobuf/src/test/java/org/apache/avro/protobuf/TestProtobuf.java
@@ -25,7 +25,7 @@ import org.apache.avro.io.DecoderFactory;
 import org.apache.avro.io.Encoder;
 import org.apache.avro.io.EncoderFactory;
 import org.apache.avro.specific.SpecificData;
-
+import org.apache.commons.compress.utils.Lists;
 import org.junit.Test;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
@@ -88,6 +88,28 @@ public class TestProtobuf {
   }
 
   @Test
+  public void testMessageWithEmptyArray() throws Exception {
+    Foo foo = Foo.newBuilder().setInt32(5).setBool(true).build();
+    ByteArrayOutputStream bao = new ByteArrayOutputStream();
+    ProtobufDatumWriter<Foo> w = new ProtobufDatumWriter<>(Foo.class);
+    Encoder e = EncoderFactory.get().binaryEncoder(bao, null);
+    w.write(foo, e);
+    e.flush();
+    Foo o = new ProtobufDatumReader<>(Foo.class).read(null,
+        DecoderFactory.get().binaryDecoder(new ByteArrayInputStream(bao.toByteArray()), null));
+
+    assertEquals(foo.getInt32(), o.getInt32());
+    assertEquals(foo.getBool(), o.getBool());
+    assertEquals(0, o.getFooArrayCount());
+  }
+
+  @Test
+  public void testEmptyArray() throws Exception {
+    Schema s = ProtobufData.get().getSchema(Foo.class);
+    assertEquals(s.getField("fooArray").defaultVal(), Lists.newArrayList());
+  }
+
+  @Test
   public void testNestedEnum() throws Exception {
     Schema s = ProtobufData.get().getSchema(N.class);
     assertEquals(N.class.getName(), SpecificData.get().getClass(s).getName());