当前位置: 动力学知识库 > 问答 > 编程问答 >

javascript - API standard for JS / C# interface - Camel vs. Pascal case

问题描述:

We have a system where a server written in C# implements a REST interface and the client is written in JS, most of the data is passed as JSON.

In a way there is here a collision between the camelCase and PascalCase worlds.

The parameters mostly derive from names within the server and are all in PascalCase.

The JS front end is written using camelCase and is expecting that the server will accept parameters like this since JSON comes from the JS world.

What would constitute an acceptable solution, and why?

网友答案:

For Web API method's parameter use "camelCase", I think this suggested name convention for method's parameters in the .NET

For the properties use JSON serialization attributes

public class Person
{
    [JsonProperty("id")]
    public int Id { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }
}

Serialized object will looks like:

{ "id": 10, "name": "My Name" }

With this approach your C# code stay with PascalCase and client side(Javascript) will use camelCase.

网友答案:

I do not know if it is full answer because it is not clear what exactly you want to achieve.

Obviously C# is Pascal case and JSON is Camel case.

So for our web ASP.Net Web API app we have implemented DataConverter for 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
}

It converts "someProperty" to "SomeProperty" when JSON converted to C# objects and "SomeProperty" to "someProperty" in the opposite direction. It allows us to use dynamic keyword in API controllers (attribute [FromBody] is required for input parameter in case of ASP.Net Core project).

分享给朋友:
您可能感兴趣的文章:
随机阅读: