Allow the original field name (rather than camel-cased) when parsing JSON
diff --git a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs
index d3c3a48..aa090d1 100644
--- a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs
+++ b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs
@@ -72,6 +72,14 @@
         }
 
         [Test]
+        public void OriginalFieldNameAccepted()
+        {
+            var json = "{ \"single_int32\": 10 }";
+            var expected = new TestAllTypes { SingleInt32 = 10 };
+            Assert.AreEqual(expected, TestAllTypes.Parser.ParseJson(json));
+        }
+
+        [Test]
         public void SourceContextRoundtrip()
         {
             AssertRoundtrip(new SourceContext { FileName = "foo.proto" });
diff --git a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
index d1732b2..f43803a 100644
--- a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
@@ -92,11 +92,22 @@
                 new FieldDescriptor(field, file, this, index, 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)));
+            jsonFieldMap = CreateJsonFieldMap(fieldsInNumberOrder);
             file.DescriptorPool.AddSymbol(this);
             Fields = new FieldCollection(this);
         }
 
+        private static ReadOnlyDictionary<string, FieldDescriptor> CreateJsonFieldMap(IList<FieldDescriptor> fields)
+        {
+            var map = new Dictionary<string, FieldDescriptor>();
+            foreach (var field in fields)
+            {
+                map[JsonFormatter.ToCamelCase(field.Name)] = field;
+                map[field.Name] = field;
+            }
+            return new ReadOnlyDictionary<string, FieldDescriptor>(map);
+        }
+
         /// <summary>
         /// The brief name of the descriptor's target.
         /// </summary>
@@ -255,9 +266,10 @@
             // 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
+            /// Returns a read-only dictionary mapping the field names in this message as they're available
             /// 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>.
+            /// in the message would result two entries, one with a key <c>fooBar</c> and one with a key
+            /// <c>foo_bar</c>, both referring to the same field.
             /// </value>
             internal IDictionary<string, FieldDescriptor> ByJsonName() => messageDescriptor.jsonFieldMap;