我们有一个系统,其中用C#编写的服务器实现REST接口,客户端用JS编写,大部分数据以JSON形式传递。JS/C#接口的API标准 - Camel与Pascal案例
在某种程度上,骆驼套和PascalCase世界之间存在冲突。
参数主要来源于服务器中的名称,全部都在PascalCase中。
JS前端是使用camelCase编写的,并期望服务器接受这样的参数,因为JSON来自JS世界。
什么构成可接受的解决方案,为什么?
我们有一个系统,其中用C#编写的服务器实现REST接口,客户端用JS编写,大部分数据以JSON形式传递。JS/C#接口的API标准 - Camel与Pascal案例
在某种程度上,骆驼套和PascalCase世界之间存在冲突。
参数主要来源于服务器中的名称,全部都在PascalCase中。
JS前端是使用camelCase编写的,并期望服务器接受这样的参数,因为JSON来自JS世界。
什么构成可接受的解决方案,为什么?
对于Web API方法的参数使用的“驼峰”,我觉得这个建议的名称约定方法的在.NET参数
有关属性使用JSON serialization attributes
public class Person
{
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
}
序列化对象将是这样的:
{ "id": 10, "name": "My Name" }
使用这种方法,您的C#代码保留在PascalCase中,客户端(Javascript)将使用camelCase。
我不知道这个,但它是最有意义的! – Thomas
我不知道它是否完整答案,因为目前尚不清楚你想要达到什么目的。
显然C#是Pascal的情况下,JSON是骆驼的情况。
所以对于我们的网络ASP.Net的Web API的应用程序,我们已经实现了DataConverter Json.NET:
public class DataConverter : JsonConverter
{
#region Overriding
public override bool CanRead
{
get { return true; }
}
public override bool CanWrite
{
get { return true; }
}
public override bool CanConvert(Type objectType)
{
return true;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
return this.ReadValue(reader);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
this.WriteValue(writer, value, serializer);
}
#endregion
#region Assistants
private object ReadValue(JsonReader reader)
{
while (reader.TokenType == JsonToken.Comment)
{
if (reader.Read() == false)
throw new Exception("Unexpected end.");
}
switch (reader.TokenType)
{
case JsonToken.StartObject:
return this.ReadObject(reader);
case JsonToken.StartArray:
return this.ReadList(reader);
default:
if (this.CheckPrimitive(reader.TokenType) == true)
return reader.Value;
throw new Exception(string.Format(CultureInfo.InvariantCulture, "Unexpected token when converting ExpandoObject: {0}", reader.TokenType));
}
}
private object ReadList(JsonReader reader)
{
List<object> collection = new List<object>();
while (reader.Read() == true)
{
switch (reader.TokenType)
{
case JsonToken.Comment:
break;
case JsonToken.EndArray:
return collection;
default:
object value = this.ReadValue(reader);
collection.Add(value);
break;
}
}
throw new Exception("Unexpected end.");
}
private object ReadObject(JsonReader reader)
{
IDictionary<string, object> expando = new ExpandoObject();
while (reader.Read() == true)
{
switch (reader.TokenType)
{
case JsonToken.PropertyName:
string property = reader.Value.ToString().ToCase(Casing.Pascal);
if (reader.Read() == false)
throw new Exception("Unexpected end.");
object value = this.ReadValue(reader);
expando[property] = value;
break;
case JsonToken.Comment:
break;
case JsonToken.EndObject:
return expando;
}
}
throw new Exception("Unexpected end.");
}
private void WriteValue(JsonWriter writer, object value, JsonSerializer serializer)
{
if (this.CheckPrimitive(value) == true)
{
writer.WriteValue(value);
return;
}
if (value is Guid)
{
this.WriteValue(writer, (Guid)value, serializer);
return;
}
if (value is MyType)
{
this.WriteValue(writer, (MyType)value, serializer);
return;
}
if (value is IDynamicMetaObjectProvider && value is IDictionary<string, object>)
{
this.WriteObject(writer, (IDictionary<string, object>)value, serializer);
return;
}
if (value is IEnumerable)
{
IEnumerable enumerable = value as IEnumerable;
this.WriteArray(writer, enumerable, serializer);
return;
}
this.WriteObject(writer, value, serializer);
}
private void WriteValue(JsonWriter writer, Guid guid, JsonSerializer serializer)
{
writer.WriteValue(guid.ToString());
}
private void WriteValue(JsonWriter writer, MyType myType, JsonSerializer serializer)
{
writer.WriteValue(myType.ToString());
}
private void WriteArray(JsonWriter writer, IEnumerable enumerable, JsonSerializer serializer)
{
writer.WriteStartArray();
foreach (object value in enumerable)
{
this.WriteValue(writer, value, serializer);
}
writer.WriteEndArray();
}
private void WriteObject(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteStartObject();
foreach (PropertyInfo properties in value.GetType().GetProperties())
{
ParameterInfo[] parameters = properties.GetGetMethod().GetParameters();
if (parameters.Length == 0)
{
writer.WritePropertyName(properties.Name.ToCase(Casing.Camel));
this.WriteValue(writer, properties.GetValue(value), serializer);
}
}
writer.WriteEndObject();
}
private void WriteObject(JsonWriter writer, IDictionary<string, object> value, JsonSerializer serializer)
{
writer.WriteStartObject();
foreach (KeyValuePair<string, object> properties in value)
{
writer.WritePropertyName(properties.Key.ToCase(Casing.Camel)); // Implement own casing...
this.WriteValue(writer, properties.Value, serializer);
}
writer.WriteEndObject();
}
private bool CheckPrimitive(JsonToken token)
{
switch (token)
{
case JsonToken.Integer:
case JsonToken.Float:
case JsonToken.String:
case JsonToken.Boolean:
case JsonToken.Null:
case JsonToken.Undefined:
case JsonToken.Date:
case JsonToken.Bytes:
return true;
}
return false;
}
private bool CheckPrimitive(object value)
{
if (value == null)
return true;
if (value is bool)
return true;
if (value is byte)
return true;
if (value is sbyte)
return true;
if (value is short)
return true;
if (value is ushort)
return true;
if (value is int)
return true;
if (value is uint)
return true;
if (value is long)
return true;
if (value is ulong)
return true;
if (value is float)
return true;
if (value is double)
return true;
if (value is decimal)
return true;
if (value is char)
return true;
if (value is string)
return true;
if (value is DateTime)
return true;
if (value is Enum)
return true;
return false;
}
#endregion
}
它把 “someProperty” 到 “SomeProperty” 当JSON转换为C#对象和 “SomeProperty” 来“someProperty”的方向相反。它允许我们在API控制器中使用动态关键字(在ASP.Net Core项目的情况下,输入参数需要[FromBody]属性)。
没有真正正确的答案。不过,我的建议是让你的后端对你的API不可见,并且根据API的使用情况进行任何约定,在这种情况下,js约定 –
让双方都使用camelCase,让双方都使用PascalCase,或者编写一个解释器来转换两者之间。这就是所有可以说的。 – Abion47
听起来像是左手没在注意右手在做什么 – charlietfl