2016-10-02 90 views
0

我们有一个系统,其中用C#编写的服务器实现REST接口,客户端用JS编写,大部分数据以JSON形式传递。JS/C#接口的API标准 - Camel与Pascal案例

在某种程度上,骆驼套和PascalCase世界之间存在冲突。

参数主要来源于服务器中的名称,全部都在PascalCase中。

JS前端是使用camelCase编写的,并期望服务器接受这样的参数,因为JSON来自JS世界。

什么构成可接受的解决方案,为什么?

+0

没有真正正确的答案。不过,我的建议是让你的后端对你的API不可见,并且根据API的使用情况进行任何约定,在这种情况下,js约定 –

+1

让双方都使用camelCase,让双方都使用PascalCase,或者编写一个解释器来转换两者之间。这就是所有可以说的。 – Abion47

+0

听起来像是左手没在注意右手在做什么 – charlietfl

回答

0

对于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。

+0

我不知道这个,但它是最有意义的! – Thomas

0

我不知道它是否完整答案,因为目前尚不清楚你想要达到什么目的。

显然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]属性)。

+0

是的,但实际上它浪费了CPU时间来处理人类语义,不是吗? – Thomas

+0

你可以测试..但它是基于图书馆本身使用的原始转换器。如果性能不够,那么你可以优化算法。 – Maxim