You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@avro.apache.org by rs...@apache.org on 2021/10/06 10:47:59 UTC

[avro] branch master updated: AVRO-2633: C# include schema doc (#1070)

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

rskraba 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 a86dde2  AVRO-2633: C# include schema doc (#1070)
a86dde2 is described below

commit a86dde293841a5f7856c11c799ca6561e6745419
Author: tom-j-irvine <66...@users.noreply.github.com>
AuthorDate: Wed Oct 6 04:47:52 2021 -0600

    AVRO-2633: C# include schema doc (#1070)
    
    * AVRO-2633 - csharp include schema doc
    
    * AVRO-2633 - update tests for doc attribute
    
    updated TestRecordDoc to test both the parsing and reserializtion - thanks @BarryDahlberg
    updated the doc serialization logic to preserve empty strings (and only eliminate nulls)
    
    Co-authored-by: Tom Irvine <to...@simplement.us>
    Co-authored-by: RyanSkraba <ry...@skraba.com>
---
 lang/csharp/src/apache/main/Schema/JsonHelper.cs  | 15 ++++++++++++++-
 lang/csharp/src/apache/main/Schema/NamedSchema.cs | 10 ++++++----
 lang/csharp/src/apache/main/Schema/Schema.cs      |  2 +-
 lang/csharp/src/apache/main/Schema/SchemaName.cs  | 17 +++++++++++++----
 lang/csharp/src/apache/test/Schema/SchemaTests.cs | 15 ++++++++++++---
 5 files changed, 46 insertions(+), 13 deletions(-)

diff --git a/lang/csharp/src/apache/main/Schema/JsonHelper.cs b/lang/csharp/src/apache/main/Schema/JsonHelper.cs
index 87887f5..1ca51cb 100644
--- a/lang/csharp/src/apache/main/Schema/JsonHelper.cs
+++ b/lang/csharp/src/apache/main/Schema/JsonHelper.cs
@@ -98,7 +98,7 @@ namespace Avro
         }
 
         /// <summary>
-        /// Writes JSON property name and value if value is not null
+        /// Writes JSON property name and value if value is not null or empty
         /// </summary>
         /// <param name="writer">JSON writer</param>
         /// <param name="key">property name</param>
@@ -110,5 +110,18 @@ namespace Avro
             writer.WriteValue(value);
         }
 
+
+        /// <summary>
+        /// Write JSON property name and value, if value is not null
+        /// </summary>
+        /// <param name="writer">JSON writer</param>
+        /// <param name="key">property name</param>
+        /// <param name="value">property value</param>
+        internal static void writeIfNotNull(JsonTextWriter writer, string key, string value)
+        {
+            if (value == null) return;
+            writer.WritePropertyName(key);
+            writer.WriteValue(value);
+        }
     }
 }
diff --git a/lang/csharp/src/apache/main/Schema/NamedSchema.cs b/lang/csharp/src/apache/main/Schema/NamedSchema.cs
index ca54440..fe9d214 100644
--- a/lang/csharp/src/apache/main/Schema/NamedSchema.cs
+++ b/lang/csharp/src/apache/main/Schema/NamedSchema.cs
@@ -78,6 +78,7 @@ namespace Avro
         internal static NamedSchema NewInstance(JObject jo, PropertyMap props, SchemaNames names, string encspace)
         {
             string type = JsonHelper.GetRequiredString(jo, "type");
+            string doc = JsonHelper.GetOptionalString(jo, "doc");
             switch (type)
             {
                 case "fixed":
@@ -90,7 +91,7 @@ namespace Avro
                     return RecordSchema.NewInstance(Type.Error, jo, props, names, encspace);
                 default:
                     NamedSchema result;
-                    if (names.TryGetValue(type, null, encspace, out result))
+                    if (names.TryGetValue(type, null, encspace, doc, out result))
                         return result;
                     return null;
             }
@@ -128,7 +129,8 @@ namespace Avro
         {
             String n = JsonHelper.GetOptionalString(jtok, "name");      // Changed this to optional string for anonymous records in messages
             String ns = JsonHelper.GetOptionalString(jtok, "namespace");
-            return new SchemaName(n, ns, encspace);
+            String d = JsonHelper.GetOptionalString(jtok, "doc");
+            return new SchemaName(n, ns, encspace, d);
         }
 
         /// <summary>
@@ -136,7 +138,7 @@ namespace Avro
         /// </summary>
         /// <param name="jtok">JSON object to read</param>
         /// <param name="space">namespace of the name this alias is for</param>
-        /// <param name="encspace">enclosing namespace of the name this alias is for</param>
+        /// <param name="encspace">enclosing namespace of the name this alias is for</param>        
         /// <returns>List of SchemaName that represents the list of alias. If no 'aliases' specified, then it returns null.</returns>
         protected static IList<SchemaName> GetAliases(JToken jtok, string space, string encspace)
         {
@@ -153,7 +155,7 @@ namespace Avro
                 if (jalias.Type != JTokenType.String)
                     throw new SchemaParseException($"Aliases must be of format JSON array of strings at '{jtok.Path}'");
 
-                aliases.Add(new SchemaName((string)jalias, space, encspace));
+                aliases.Add(new SchemaName((string)jalias, space, encspace, null));
             }
             return aliases;
         }
diff --git a/lang/csharp/src/apache/main/Schema/Schema.cs b/lang/csharp/src/apache/main/Schema/Schema.cs
index 94b96db..d14b016 100644
--- a/lang/csharp/src/apache/main/Schema/Schema.cs
+++ b/lang/csharp/src/apache/main/Schema/Schema.cs
@@ -166,7 +166,7 @@ namespace Avro
                 if (null != ps) return ps;
 
                 NamedSchema schema = null;
-                if (names.TryGetValue(value, null, encspace, out schema)) return schema;
+                if (names.TryGetValue(value, null, encspace, null, out schema)) return schema;
 
                 throw new SchemaParseException($"Undefined name: {value} at '{jtok.Path}'");
             }
diff --git a/lang/csharp/src/apache/main/Schema/SchemaName.cs b/lang/csharp/src/apache/main/Schema/SchemaName.cs
index ced24ee..20cc1b4 100644
--- a/lang/csharp/src/apache/main/Schema/SchemaName.cs
+++ b/lang/csharp/src/apache/main/Schema/SchemaName.cs
@@ -21,7 +21,7 @@ using System.Collections.Generic;
 namespace Avro
 {
     /// <summary>
-    /// Class to store schema name, namespace and enclosing namespace
+    /// Class to store schema name, namespace, enclosing namespace and documentation
     /// </summary>
     public class SchemaName
     {
@@ -44,6 +44,11 @@ namespace Avro
         public String EncSpace { get; private set; }
 
         /// <summary>
+        /// Documentation for the schema
+        /// </summary>
+        public String Documentation { get; private set; }
+
+        /// <summary>
         /// Namespace.Name of the schema
         /// </summary>
         public String Fullname { get { return fullName; } }
@@ -59,7 +64,8 @@ namespace Avro
         /// <param name="name">name of the schema</param>
         /// <param name="space">namespace of the schema</param>
         /// <param name="encspace">enclosing namespace of the schema</param>
-        public SchemaName(String name, String space, String encspace)
+        /// <param name="documentation">documentation o fthe schema</param>
+        public SchemaName(String name, String space, String encspace, String documentation)
         {
             if (name == null)
             {                         // anonymous
@@ -81,6 +87,7 @@ namespace Avro
                 this.Name = parts[parts.Length - 1];
                 this.EncSpace = encspace;
             }
+            this.Documentation = documentation;
             fullName = string.IsNullOrEmpty(Namespace) ? this.Name : Namespace + "." + this.Name;
         }
 
@@ -104,6 +111,7 @@ namespace Avro
             if (null != this.Name)  // write only if not anonymous
             {
                 JsonHelper.writeIfNotNullOrEmpty(writer, "name", this.Name);
+                JsonHelper.writeIfNotNull(writer, "doc", this.Documentation);
                 if (!String.IsNullOrEmpty(this.Space))
                     JsonHelper.writeIfNotNullOrEmpty(writer, "namespace", this.Space);
                 else if (!String.IsNullOrEmpty(this.EncSpace)) // need to put enclosing name space for code generated classes
@@ -210,11 +218,12 @@ namespace Avro
         /// <param name="name">name of the schema</param>
         /// <param name="space">namespace of the schema</param>
         /// <param name="encspace">enclosing namespace of the schema</param>
+        /// <param name="documentation">documentation for the schema</param>
         /// <param name="schema">schema object found</param>
         /// <returns>true if name is found in the map, false otherwise</returns>
-        public bool TryGetValue(string name, string space, string encspace, out NamedSchema schema)
+        public bool TryGetValue(string name, string space, string encspace, string documentation, out NamedSchema schema)
         {
-            SchemaName schemaname = new SchemaName(name, space, encspace);
+            SchemaName schemaname = new SchemaName(name, space, encspace, documentation);
             return Names.TryGetValue(schemaname, out schema);
         }
 
diff --git a/lang/csharp/src/apache/test/Schema/SchemaTests.cs b/lang/csharp/src/apache/test/Schema/SchemaTests.cs
index 7145670..93a86a9 100644
--- a/lang/csharp/src/apache/test/Schema/SchemaTests.cs
+++ b/lang/csharp/src/apache/test/Schema/SchemaTests.cs
@@ -69,8 +69,12 @@ namespace Avro.Test
             typeof(SchemaParseException), Description = "No fields")]
         [TestCase("{\"type\":\"record\",\"name\":\"LongList\", \"fields\": \"hi\"}",
             typeof(SchemaParseException), Description = "Fields not an array")]
-        [TestCase("[{\"type\": \"record\",\"name\": \"Test\",\"namespace\":\"ns1\",\"fields\": [{\"name\": \"f\",\"type\": \"long\"}]}," + 
+        [TestCase("[{\"type\": \"record\",\"name\": \"Test\",\"namespace\":\"ns1\",\"fields\": [{\"name\": \"f\",\"type\": \"long\"}]}," +
                    "{\"type\": \"record\",\"name\": \"Test\",\"namespace\":\"ns2\",\"fields\": [{\"name\": \"f\",\"type\": \"long\"}]}]")]
+
+        // Doc
+        [TestCase("{\"type\": \"record\",\"name\": \"Test\",\"doc\": \"Test Doc\",\"fields\": [{\"name\": \"f\",\"type\": \"long\"}]}")]
+
         // Enum
         [TestCase("{\"type\": \"enum\", \"name\": \"Test\", \"symbols\": [\"A\", \"B\"]}")]
         [TestCase("{\"type\": \"enum\", \"name\": \"Status\", \"symbols\": \"Normal Caution Critical\"}",
@@ -218,6 +222,11 @@ namespace Avro.Test
             var rs = Schema.Parse(s) as RecordSchema;
             Assert.IsNotNull(rs);
             Assert.AreEqual(expectedDoc, rs.Documentation);
+
+            var roundTrip = Schema.Parse(rs.ToString()) as RecordSchema;
+
+            Assert.IsNotNull(roundTrip);
+            Assert.AreEqual(expectedDoc, roundTrip.Documentation);
         }
 
         [TestCase("{\"type\": \"enum\", \"name\": \"Test\", \"symbols\": [\"A\", \"B\"]}",
@@ -250,7 +259,7 @@ namespace Avro.Test
         }
 
         [TestCase("{\"type\": \"enum\", \"name\": \"Test\", \"symbols\": [\"Unknown\", \"A\", \"B\"], \"default\": \"Unknown\" }", "Unknown")]
-        public void TestEnumDefault(string s, string expectedToken) 
+        public void TestEnumDefault(string s, string expectedToken)
         {
             var es = Schema.Parse(s) as EnumSchema;
             Assert.IsNotNull(es);
@@ -348,7 +357,7 @@ namespace Avro.Test
         [TestCase("a", "o.a.h", ExpectedResult = "o.a.h.a")]
         public string testFullname(string s1, string s2)
         {
-            var name = new SchemaName(s1, s2, null);
+            var name = new SchemaName(s1, s2, null, null);
             return name.Fullname;
         }