From b8e8e1dd865541c3dcd62b3ab5cb6e41154541ad Mon Sep 17 00:00:00 2001
From: MattMo <matt@montoyatech.com>
Date: Fri, 23 Feb 2024 16:23:54 -0800
Subject: [PATCH] Bumped package version to 1.8.2. Added the ability to use
 json names in the Javascript Client generator if a JsonProperty exists on a
 field or a property.

---
 Rest.Net.Example/Program.cs               |  9 ++-
 Rest.Net/Rest.Net.csproj                  |  2 +-
 Rest.Net/RestJavascriptClientGenerator.cs | 75 +++++++++++++++++++----
 Rest.Net/RouteListener.cs                 |  3 +-
 4 files changed, 74 insertions(+), 15 deletions(-)

diff --git a/Rest.Net.Example/Program.cs b/Rest.Net.Example/Program.cs
index 1624cc2..98ce619 100644
--- a/Rest.Net.Example/Program.cs
+++ b/Rest.Net.Example/Program.cs
@@ -11,17 +11,22 @@ using System.Collections;
 using Newtonsoft.Json.Linq;
 using System.Web;
 using System.Net.Http;
+using Newtonsoft.Json;
 
 namespace MontoyaTech.Rest.Net.Example
 {
     public class BaseUser
     {
+        [JsonProperty("id")]
         public string Id;
 
+        [JsonProperty("firstInitial")]
         public char FirstInitial;
 
+        [JsonProperty("role")]
         public UserRole Role { get; set; }
 
+        [JsonProperty("permissions")]
         public List<Permission> Permissions;
 
         public class Permission
@@ -94,11 +99,11 @@ namespace MontoyaTech.Rest.Net.Example
 
             File.WriteAllText("Client.cs", listener.GenerateCSharpClient());
 
-            File.WriteAllText("Client.js", listener.GenerateJavascriptClient());
+            File.WriteAllText("Client.js", listener.GenerateJavascriptClient(useJsonNames: true));
 
             File.WriteAllText("StaticClient.cs", listener.GenerateCSharpClient("StaticClient", staticCode: true));
 
-            File.WriteAllText("StaticClient.js", listener.GenerateJavascriptClient("StaticClient", staticCode: true));
+            File.WriteAllText("StaticClient.js", listener.GenerateJavascriptClient("StaticClient", staticCode: true, useJsonNames: true));
 
             Console.WriteLine("Generated Client.cs, Client.js, StaticClient.cs, StaticClient.js");
 
diff --git a/Rest.Net/Rest.Net.csproj b/Rest.Net/Rest.Net.csproj
index 7504c34..d43320c 100644
--- a/Rest.Net/Rest.Net.csproj
+++ b/Rest.Net/Rest.Net.csproj
@@ -17,7 +17,7 @@
     <AssemblyName>MontoyaTech.Rest.Net</AssemblyName>
     <RootNamespace>MontoyaTech.Rest.Net</RootNamespace>
     <GenerateDocumentationFile>True</GenerateDocumentationFile>
-    <Version>1.8.1</Version>
+    <Version>1.8.2</Version>
     <PackageReleaseNotes></PackageReleaseNotes>
     <PackageIcon>Logo_Symbol_Black_Outline.png</PackageIcon>
   </PropertyGroup>
diff --git a/Rest.Net/RestJavascriptClientGenerator.cs b/Rest.Net/RestJavascriptClientGenerator.cs
index 2635e5b..f8bba0a 100644
--- a/Rest.Net/RestJavascriptClientGenerator.cs
+++ b/Rest.Net/RestJavascriptClientGenerator.cs
@@ -20,6 +20,11 @@ namespace MontoyaTech.Rest.Net
         /// </summary>
         public bool StaticCode = false;
 
+        /// <summary>
+        /// Whether or not to use Json Property names instead of the Field/Property names.
+        /// </summary>
+        public bool UseJsonNames = false;
+
         /// <summary>
         /// Generates a Javascript Client from a given set of routes and returns it.
         /// </summary>
@@ -271,12 +276,12 @@ namespace MontoyaTech.Rest.Net
                 fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
 
             foreach (var field in fields)
-                    this.GenerateJavascriptIncludedField(field, writer);
+                this.GenerateJavascriptIncludedField(field, writer);
 
             var properties = type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public).Where(property => property.GetSetMethod() != null && property.GetGetMethod() != null).ToArray();
 
             foreach (var property in properties)
-                    this.GenerateJavascriptIncludedProperty(property, writer);
+                this.GenerateJavascriptIncludedProperty(property, writer);
 
             //Generate a helper constructor
             if (!type.IsEnum)
@@ -284,28 +289,64 @@ namespace MontoyaTech.Rest.Net
                 writer.WriteBreak().WriteLine("/**").Indent();
                 writer.WriteLine("@function");
 
+                //Docuemnt the fields
                 foreach (var field in fields)
-                    writer.WriteLine($"@param {{{this.GetTypeFullyResolvedName(field.FieldType)}}} {field.Name}");
+                {
+                    if (this.UseJsonNames)
+                        writer.WriteLine($"@param {{{this.GetTypeFullyResolvedName(field.FieldType)}}} {(field.GetCustomAttribute<Newtonsoft.Json.JsonPropertyAttribute>()?.PropertyName ?? field.Name)}");
+                    else
+                        writer.WriteLine($"@param {{{this.GetTypeFullyResolvedName(field.FieldType)}}} {field.Name}");
+                }
 
+                //Document the properties
                 foreach (var property in properties)
-                    writer.WriteLine($"@param {{{this.GetTypeFullyResolvedName(property.PropertyType)}}} {property.Name}");
+                {
+                    if (this.UseJsonNames)
+                        writer.WriteLine($"@param {{{this.GetTypeFullyResolvedName(property.PropertyType)}}} {(property.GetCustomAttribute<Newtonsoft.Json.JsonPropertyAttribute>()?.PropertyName ?? property.Name)}");
+                    else
+                        writer.WriteLine($"@param {{{this.GetTypeFullyResolvedName(property.PropertyType)}}} {property.Name}");
+                }
 
                 writer.Outdent().WriteLine("*/");
                 writer.Write("constructor(");
 
+                //Write the default fields
                 foreach (var field in fields)
-                    writer.WriteSeparator().Write(field.Name).Write(" = ").Write(this.GetTypeDefaultValue(field.FieldType));
+                {
+                    if (this.UseJsonNames)
+                        writer.WriteSeparator().Write(field.GetCustomAttribute<Newtonsoft.Json.JsonPropertyAttribute>()?.PropertyName ?? field.Name).Write(" = ").Write(this.GetTypeDefaultValue(field.FieldType));
+                    else
+                        writer.WriteSeparator().Write(field.Name).Write(" = ").Write(this.GetTypeDefaultValue(field.FieldType));
+                }
 
+                //Write the default properties
                 foreach (var property in properties)
-                    writer.WriteSeparator().Write(property.Name).Write(" = ").Write(this.GetTypeDefaultValue(property.PropertyType));
+                {
+                    if (this.UseJsonNames)
+                        writer.WriteSeparator().Write(property.GetCustomAttribute<Newtonsoft.Json.JsonPropertyAttribute>()?.PropertyName ?? property.Name).Write(" = ").Write(this.GetTypeDefaultValue(property.PropertyType));
+                    else
+                        writer.WriteSeparator().Write(property.Name).Write(" = ").Write(this.GetTypeDefaultValue(property.PropertyType));
+                }
 
                 writer.WriteLine(") {").Indent();
 
+                //Init the default fields
                 foreach (var field in fields)
-                    writer.Write("this.").Write(field.Name).Write(" = ").Write(field.Name).WriteLine(";");
+                {
+                    if (this.UseJsonNames)
+                        writer.Write("this.").Write(field.GetCustomAttribute<Newtonsoft.Json.JsonPropertyAttribute>()?.PropertyName ?? field.Name).Write(" = ").Write(field.GetCustomAttribute<Newtonsoft.Json.JsonPropertyAttribute>()?.PropertyName ?? field.Name).WriteLine(";");
+                    else
+                        writer.Write("this.").Write(field.Name).Write(" = ").Write(field.Name).WriteLine(";");
+                }
 
+                //Init the default properties
                 foreach (var property in properties)
-                    writer.Write("this.").Write(property.Name).Write(" = ").Write(property.Name).WriteLine(";");
+                {
+                    if (this.UseJsonNames)
+                        writer.Write("this.").Write(property.GetCustomAttribute<Newtonsoft.Json.JsonPropertyAttribute>()?.PropertyName ?? property.Name).Write(" = ").Write(property.GetCustomAttribute<Newtonsoft.Json.JsonPropertyAttribute>()?.PropertyName ?? property.Name).WriteLine(";");
+                    else
+                        writer.Write("this.").Write(property.Name).Write(" = ").Write(property.Name).WriteLine(";");
+                }
 
                 writer.Outdent().WriteLine("}");
             }
@@ -417,12 +458,20 @@ namespace MontoyaTech.Rest.Net
             if (field.DeclaringType != null && field.DeclaringType.IsEnum)
             {
                 writer.WriteLine($"/** @type {{{GetTypeFullyResolvedName(field.DeclaringType)}}} */");
-                writer.WriteLine($"static {field.Name} = {field.GetRawConstantValue()};");
+
+                if (this.UseJsonNames)
+                    writer.WriteLine($"static {(field.GetCustomAttribute<Newtonsoft.Json.JsonPropertyAttribute>()?.PropertyName ?? field.Name)} = {field.GetRawConstantValue()};");
+                else
+                    writer.WriteLine($"static {field.Name} = {field.GetRawConstantValue()};");
             }
             else
             {
                 writer.WriteLine($"/** @type {{{GetTypeFullyResolvedName(field.FieldType)}}} */");
-                writer.WriteLine($"{field.Name} = {GetTypeDefaultValue(field.FieldType)};");
+
+                if (this.UseJsonNames)
+                    writer.WriteLine($"{(field.GetCustomAttribute<Newtonsoft.Json.JsonPropertyAttribute>()?.PropertyName ?? field.Name)} = {GetTypeDefaultValue(field.FieldType)};");
+                else
+                    writer.WriteLine($"{field.Name} = {GetTypeDefaultValue(field.FieldType)};");
             }
         }
 
@@ -431,7 +480,11 @@ namespace MontoyaTech.Rest.Net
             writer.WriteBreak();
 
             writer.WriteLine($"/** @type {{{GetTypeFullyResolvedName(property.PropertyType)}}} */");
-            writer.WriteLine($"{property.Name} = {GetTypeDefaultValue(property.PropertyType)};");
+
+            if (this.UseJsonNames)
+                writer.WriteLine($"{(property.GetCustomAttribute<Newtonsoft.Json.JsonPropertyAttribute>()?.PropertyName ?? property.Name)} = {GetTypeDefaultValue(property.PropertyType)};");
+            else
+                writer.WriteLine($"{property.Name} = {GetTypeDefaultValue(property.PropertyType)};");
         }
 
         protected internal virtual void GenerateJavascriptRouteGroups(Dictionary<string, List<Route>> groups, CodeWriter writer)
diff --git a/Rest.Net/RouteListener.cs b/Rest.Net/RouteListener.cs
index df28b9c..1fc8f63 100644
--- a/Rest.Net/RouteListener.cs
+++ b/Rest.Net/RouteListener.cs
@@ -256,12 +256,13 @@ namespace MontoyaTech.Rest.Net
         /// <param name="clientName"></param>
         /// <param name="staticCode"></param>
         /// <returns></returns>
-        public string GenerateJavascriptClient(string clientName = "Client", bool staticCode = false)
+        public string GenerateJavascriptClient(string clientName = "Client", bool staticCode = false, bool useJsonNames = false)
         {
             var generator = new RestJavascriptClientGenerator();
 
             generator.ClientName = clientName;
             generator.StaticCode = staticCode;
+            generator.UseJsonNames = useJsonNames;
 
             return generator.Generate(this);
         }