You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@avro.apache.org by "ASF GitHub Bot (JIRA)" <ji...@apache.org> on 2018/11/29 19:43:00 UTC

[jira] [Commented] (AVRO-2131) Records with unions with self references fail to parse.

    [ https://issues.apache.org/jira/browse/AVRO-2131?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16703705#comment-16703705 ] 

ASF GitHub Bot commented on AVRO-2131:
--------------------------------------

dkulp closed pull request #278: AVRO-2131 Modified Schema.parse(JsonNode schema, Names names) to allow Unions with self referencess.
URL: https://github.com/apache/avro/pull/278
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/lang/java/avro/src/main/java/org/apache/avro/Schema.java b/lang/java/avro/src/main/java/org/apache/avro/Schema.java
index a87c7a27c..f0d1f867d 100644
--- a/lang/java/avro/src/main/java/org/apache/avro/Schema.java
+++ b/lang/java/avro/src/main/java/org/apache/avro/Schema.java
@@ -1404,8 +1404,13 @@ static Schema parse(JsonNode schema, Names names) {
           throw new SchemaParseException("Invalid or no size: "+schema);
         result = new FixedSchema(name, doc, sizeNode.intValue());
         if (name != null) names.add(result);
-      } else
+      } else {  //For unions with self reference
+        Name nameFromType = new Name(type, names.space);
+        if (names.containsKey(nameFromType)) {
+          return names.get(nameFromType);
+        }
         throw new SchemaParseException("Type not supported: "+type);
+      }
       Iterator<String> i = schema.fieldNames();
 
       Set reserved = SCHEMA_RESERVED;
diff --git a/lang/java/avro/src/test/java/org/apache/avro/TestUnionSelfReference.java b/lang/java/avro/src/test/java/org/apache/avro/TestUnionSelfReference.java
new file mode 100644
index 000000000..fa3c23d64
--- /dev/null
+++ b/lang/java/avro/src/test/java/org/apache/avro/TestUnionSelfReference.java
@@ -0,0 +1,114 @@
+package org.apache.avro;
+
+import org.slf4j.LoggerFactory;
+
+import static org.junit.Assert.*;
+
+import org.apache.avro.Schema.Field;
+import org.apache.avro.Schema.Type;
+import org.junit.Test;
+import org.slf4j.Logger;
+
+public class TestUnionSelfReference {
+  /** The logger for TestUnionSelfReference */
+  @SuppressWarnings("unused")
+  private static final Logger LOGGER = LoggerFactory.getLogger(TestUnionSelfReference.class);
+  
+  private static final String SIMPLE_BINARY_TREE =
+	  "{"
+	  +"    \"namespace\": \"tree\","
+	  +"    \"type\": \"record\","
+	  +"    \"name\": \"Node\","
+	  +"    \"fields\": ["
+	  +"      {"
+	  +"        \"name\": \"left\","
+	  +"        \"type\": ["
+	  +"          \"null\","
+	  +"          {"
+	  +"            \"type\": \"Node\""
+	  +"          }"
+	  +"        ],"
+	  +"        \"default\": null"
+	  +"      },"
+	  +"      {"
+	  +"        \"name\": \"right\","
+	  +"        \"type\": ["
+	  +"          \"null\","
+	  +"          {"
+	  +"            \"type\": \"Node\""
+	  +"          }"
+	  +"        ],"
+	  +"        \"default\": null"
+	  +"      }"
+	  +"    ]"
+	  +"  }";
+  
+  private static final String THREE_TYPE_UNION =
+	  "{"
+	  +"    \"namespace\": \"tree\","
+	  +"    \"type\": \"record\","
+	  +"    \"name\": \"Node\","
+	  +"    \"fields\": ["
+	  +"      {"
+	  +"        \"name\": \"left\","
+	  +"        \"type\": ["
+	  +"          \"null\","
+	  +"          \"string\","
+	  +"          {"
+	  +"            \"type\": \"Node\""
+	  +"          }"
+	  +"        ],"
+	  +"        \"default\": null"
+	  +"      },"
+	  +"      {"
+	  +"        \"name\": \"right\","
+	  +"        \"type\": ["
+	  +"          \"null\","
+	  +"          \"string\","
+	  +"          {"
+	  +"            \"type\": \"Node\""
+	  +"          }"
+	  +"        ],"
+	  +"        \"default\": null"
+	  +"      }"
+	  +"    ]"
+	  +"  }";
+  @Test
+  public void testSelfReferenceInUnion(){ 
+     Schema schema = new Schema.Parser().parse(SIMPLE_BINARY_TREE);
+     Field leftField = schema.getField("left");
+     assertEquals(JsonProperties.NULL_VALUE,leftField.defaultVal());
+     final Schema leftFieldSchema = leftField.schema();
+     assertEquals(Type.UNION,leftFieldSchema.getType());
+     assertEquals("null",leftFieldSchema.getTypes().get(0).getName());
+     assertEquals("Node",leftFieldSchema.getTypes().get(1).getName());
+     
+     Field rightField = schema.getField("right");
+     assertEquals(JsonProperties.NULL_VALUE,rightField.defaultVal());
+     final Schema rightFieldSchema = rightField.schema();
+     assertEquals(Type.UNION,rightFieldSchema.getType());
+     assertEquals("null",rightFieldSchema.getTypes().get(0).getName());
+     assertEquals("Node",rightFieldSchema.getTypes().get(1).getName());
+  }
+  
+  @Test
+  public void testSelfReferenceInThreeUnion(){ 
+     Schema schema = new Schema.Parser().parse(THREE_TYPE_UNION);
+     Field leftField = schema.getField("left");
+     assertEquals(JsonProperties.NULL_VALUE,leftField.defaultVal());
+     final Schema leftFieldSchema = leftField.schema();
+     assertEquals(Type.UNION,leftFieldSchema.getType());
+     assertEquals("null",leftFieldSchema.getTypes().get(0).getName());
+     assertEquals("string",leftFieldSchema.getTypes().get(1).getName());
+     assertEquals("Node",leftFieldSchema.getTypes().get(2).getName());
+     
+     Field rightField = schema.getField("right");
+     assertEquals(JsonProperties.NULL_VALUE,rightField.defaultVal());
+     final Schema rightFieldSchema = rightField.schema();
+     assertEquals(Type.UNION,rightFieldSchema.getType());
+     assertEquals("null",rightFieldSchema.getTypes().get(0).getName());
+     assertEquals("string",rightFieldSchema.getTypes().get(1).getName());
+     assertEquals("Node",rightFieldSchema.getTypes().get(2).getName());
+  }
+  
+}


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


> Records with unions with self references fail to parse.
> -------------------------------------------------------
>
>                 Key: AVRO-2131
>                 URL: https://issues.apache.org/jira/browse/AVRO-2131
>             Project: Apache Avro
>          Issue Type: Bug
>          Components: java
>    Affects Versions: 1.8.1
>         Environment: Java 1.8.0_152-b1
>            Reporter: Jeff Maxwell
>            Priority: Major
>
> Records with unions with self references fail to parse.
> The example below fails to parse with {{"Type not supported: Node"}}
> {code:javascript}
> [
>   {
>     "namespace": "tree",
>     "type": "record",
>     "name": "Node",
>     "fields": [
>       {
>         "name": "left",
>         "type": [
>           "null",
>           {
>             "type": "Node"
>           }
>         ],
>         "default": null
>       },
>       {
>         "name": "right",
>         "type": [
>           "null",
>           {
>             "type": "Node"
>           }
>         ],
>         "default": null
>       }
>     ]
>   }
> ]
>  {code}
> When we don't allow nullability it parses successfully:
> {code:javascript}
> [
>   {
>     "namespace": "tree",
>     "type": "record",
>     "name": "Node",
>     "fields": [
>       {
>         "name": "left",
>         "type": "Node"
>       },
>       {
>         "name": "right",
>         "type": "Node"
>       }
>     ]
>   }
> ]
>  {code}
> The root cause: When the second element of the union, {{\{"type":"Node"}\}}, is parsed there is no path that can successfully handle the {{JsonNode}}.
> The solution is to add this logic to the {{Schema.parse(JsonNode schema, Names names)}} method:
> {code:java}
>       } else {  //For unions with self reference
>         Name nameFromType = new Name(type, names.space);
>         if (names.containsKey(nameFromType)) {
>           return names.get(nameFromType);
>         }
>         throw new SchemaParseException("Type not supported: "+type);
>       }
> {code}
> Pull request attached



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)