Browse Source

Merge pull request #940 from jskeet/json-names

Move the creation of the "fields by JSON name" dictionary to the descriptor
Jon Skeet 10 năm trước cách đây
mục cha
commit
3a72a1eeaf

+ 1 - 6
csharp/src/Google.Protobuf/JsonParser.cs

@@ -37,7 +37,6 @@ using System.Collections;
 using System.Collections.Generic;
 using System.Globalization;
 using System.IO;
-using System.Linq;
 using System.Text;
 using System.Text.RegularExpressions;
 
@@ -164,11 +163,7 @@ namespace Google.Protobuf
                 throw new InvalidProtocolBufferException("Expected an object");
             }
             var descriptor = message.Descriptor;
-            // TODO: Make this more efficient, e.g. by building it once in the descriptor.
-            // Additionally, we need to consider whether to parse field names in their original proto form,
-            // and any overrides in the descriptor. But yes, all of this should be in the descriptor somehow...
-            // the descriptor can expose the dictionary.
-            var jsonFieldMap = descriptor.Fields.InDeclarationOrder().ToDictionary(field => JsonFormatter.ToCamelCase(field.Name));
+            var jsonFieldMap = descriptor.Fields.ByJsonName();
             while (true)
             {
                 token = tokenizer.Next();

+ 15 - 0
csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs

@@ -62,6 +62,7 @@ namespace Google.Protobuf.Reflection
         private readonly IList<EnumDescriptor> enumTypes;
         private readonly IList<FieldDescriptor> fieldsInDeclarationOrder;
         private readonly IList<FieldDescriptor> fieldsInNumberOrder;
+        private readonly IDictionary<string, FieldDescriptor> jsonFieldMap;
         private readonly FieldCollection fields;
         private readonly IList<OneofDescriptor> oneofs;
         // CLR representation of the type described by this descriptor, if any.
@@ -95,6 +96,8 @@ namespace Google.Protobuf.Reflection
                 (field, index) =>
                 new FieldDescriptor(field, file, this, index, generatedCodeInfo == null ? null : generatedCodeInfo.PropertyNames[index]));
             fieldsInNumberOrder = new ReadOnlyCollection<FieldDescriptor>(fieldsInDeclarationOrder.OrderBy(field => field.FieldNumber).ToArray());
+            // TODO: Use field => field.Proto.JsonName when we're confident it's appropriate. (And then use it in the formatter, too.)
+            jsonFieldMap = new ReadOnlyDictionary<string, FieldDescriptor>(fieldsInNumberOrder.ToDictionary(field => JsonFormatter.ToCamelCase(field.Name)));
             file.DescriptorPool.AddSymbol(this);
             fields = new FieldCollection(this);
         }
@@ -255,6 +258,18 @@ namespace Google.Protobuf.Reflection
                 return messageDescriptor.fieldsInNumberOrder;
             }
 
+            // TODO: consider making this public in the future. (Being conservative for now...)
+
+            /// <value>
+            /// Returns a read-only dictionary mapping the field names in this message as they're used
+            /// in the JSON representation to the field descriptors. For example, a field <c>foo_bar</c>
+            /// in the message would result in an entry with a key <c>fooBar</c>.
+            /// </value>
+            internal IDictionary<string, FieldDescriptor> ByJsonName()
+            {
+                return messageDescriptor.jsonFieldMap;
+            }
+
             /// <summary>
             /// Retrieves the descriptor for the field with the given number.
             /// </summary>