Advice for creating a convention converter

May 11, 2010 at 6:15 PM
I like keeping my model classes POCO, but I frequently need to use the JsonProperty attribute for simple name mapping, i.e., "this_property" -> ThisProperty, and other conventions, but this is the standard, because implementing a JsonConverter for this purpose is too heavy-handed (I have to handle all other values, or create interface-specific implementations of the convention mapping which can't be reused across projects). I'd like to find a way using JsonConverter or SerializerSettings to plug in conventions-based property mapping, to make model classes even simpler to maintain. What would you suggest?
Coordinator
May 11, 2010 at 10:52 PM

IContractResolver

May 12, 2010 at 1:54 AM
Edited May 12, 2010 at 1:56 AM

That works nicely.

For others, here is an example.

 

    /// <summary>
    /// Resolves all property names to JSON conventional standard,
    /// i.e. JSON name "this_is_a_property" will map to the class property ThisIsAProperty.
    /// </summary>
    public class JsonConventionResolver : DefaultContractResolver
    {
        protected override IList<JsonProperty> CreateProperties(JsonObjectContract contract)
        {
            var properties = base.CreateProperties(contract);

            foreach (var property in properties)
            {
                property.PropertyName = PascalCaseToElement(property.PropertyName);
            }

            return properties;
        }

        private static string PascalCaseToElement(string input)
        {
            if (string.IsNullOrEmpty(input))
            {
                return null;
            }

            var result = new StringBuilder();

            result.Append(char.ToLowerInvariant(input[0]));
            for (var i = 1; i < input.Length; i++)
            {
                if (char.IsLower(input[i]))
                {
                    result.Append(input[i]);
                }
                else
                {
                    result.Append("_");
                    result.Append(char.ToLowerInvariant(input[i]));
                }
            }

            return result.ToString();
        }
    }