Переглянути джерело

JSON formatting for FieldMask

Jon Skeet 10 роки тому
батько
коміт
0e30de3d6b

+ 18 - 0
csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs

@@ -388,6 +388,24 @@ namespace Google.Protobuf
             AssertJson("{ 'a': null, 'b': false, 'c': 10.5, 'd': 'text', 'e': [ 't1', 5 ], 'f': { 'nested': 'value' } }", message.ToString());
             AssertJson("{ 'a': null, 'b': false, 'c': 10.5, 'd': 'text', 'e': [ 't1', 5 ], 'f': { 'nested': 'value' } }", message.ToString());
         }
         }
 
 
+        [Test]
+        public void FieldMaskStandalone()
+        {
+            var fieldMask = new FieldMask { Paths = { "", "single", "with_underscore", "nested.field.name", "nested..double_dot" } };
+            Assert.AreEqual(",single,withUnderscore,nested.field.name,nested..doubleDot", fieldMask.ToString());
+
+            // Invalid, but we shouldn't create broken JSON...
+            fieldMask = new FieldMask { Paths = { "x\\y" } };
+            Assert.AreEqual(@"x\\y", fieldMask.ToString());
+        }
+
+        [Test]
+        public void FieldMaskField()
+        {
+            var message = new TestWellKnownTypes { FieldMaskField = new FieldMask { Paths = { "user.display_name", "photo" } } };
+            AssertJson("{ 'fieldMaskField': 'user.displayName,photo' }", JsonFormatter.Default.Format(message));
+        }
+
         /// <summary>
         /// <summary>
         /// Checks that the actual JSON is the same as the expected JSON - but after replacing
         /// Checks that the actual JSON is the same as the expected JSON - but after replacing
         /// all apostrophes in the expected JSON with double quotes. This basically makes the tests easier
         /// all apostrophes in the expected JSON with double quotes. This basically makes the tests easier

+ 21 - 1
csharp/src/Google.Protobuf/JsonFormatter.cs

@@ -36,6 +36,7 @@ using System.Globalization;
 using System.Text;
 using System.Text;
 using Google.Protobuf.Reflection;
 using Google.Protobuf.Reflection;
 using Google.Protobuf.WellKnownTypes;
 using Google.Protobuf.WellKnownTypes;
+using System.Linq;
 
 
 namespace Google.Protobuf
 namespace Google.Protobuf
 {
 {
@@ -402,6 +403,11 @@ namespace Google.Protobuf
                 MaybeWrapInString(builder, value, WriteDuration, inField);
                 MaybeWrapInString(builder, value, WriteDuration, inField);
                 return;
                 return;
             }
             }
+            if (descriptor.FullName == FieldMask.Descriptor.FullName)
+            {
+                MaybeWrapInString(builder, value, WriteFieldMask, inField);
+                return;
+            }
             if (descriptor.FullName == Struct.Descriptor.FullName)
             if (descriptor.FullName == Struct.Descriptor.FullName)
             {
             {
                 WriteStruct(builder, (IMessage) value);
                 WriteStruct(builder, (IMessage) value);
@@ -479,6 +485,12 @@ namespace Google.Protobuf
             builder.Append('s');
             builder.Append('s');
         }
         }
 
 
+        private void WriteFieldMask(StringBuilder builder, IMessage value)
+        {
+            IList paths = (IList) value.Descriptor.Fields[FieldMask.PathsFieldNumber].Accessor.GetValue(value);
+            AppendEscapedString(builder, string.Join(",", paths.Cast<string>().Select(ToCamelCase)));
+        }
+
         /// <summary>
         /// <summary>
         /// Appends a number of nanoseconds to a StringBuilder. Either 0 digits are added (in which
         /// Appends a number of nanoseconds to a StringBuilder. Either 0 digits are added (in which
         /// case no "." is appended), or 3 6 or 9 digits.
         /// case no "." is appended), or 3 6 or 9 digits.
@@ -654,6 +666,15 @@ namespace Google.Protobuf
         private void WriteString(StringBuilder builder, string text)
         private void WriteString(StringBuilder builder, string text)
         {
         {
             builder.Append('"');
             builder.Append('"');
+            AppendEscapedString(builder, text);
+            builder.Append('"');
+        }
+
+        /// <summary>
+        /// Appends the given text to the string builder, escaping as required.
+        /// </summary>
+        private void AppendEscapedString(StringBuilder builder, string text)
+        {
             for (int i = 0; i < text.Length; i++)
             for (int i = 0; i < text.Length; i++)
             {
             {
                 char c = text[i];
                 char c = text[i];
@@ -713,7 +734,6 @@ namespace Google.Protobuf
                         break;
                         break;
                 }
                 }
             }
             }
-            builder.Append('"');
         }
         }
 
 
         private const string Hex = "0123456789abcdef";
         private const string Hex = "0123456789abcdef";