christo8989
christo8989

Reputation: 6826

ViewModel Custom JsonConverter

I'm trying to create a custom JsonConverter that changes C# property names to camel case and javascript/json property names to pascal case. I feel like I'm on the right track but I'm having trouble understanding what I need to do (and I'm in a time crunch).

I realize I can add the JsonProperty attribute to my C# properties but I would prefer to apply an attribute to the class rather than each property.

public class ViewModelJsonConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return true;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var model = JObject.Load(reader);
        var properties = model.Properties();
        foreach (var prop in properties)
        {
            RenameToPascalCase(prop.Name, prop.Value);
        }
        return model;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var model = (JObject)JToken.FromObject(value);
        var properties = model.Properties();
        foreach (var prop in properties)
        {
            RenameToCamelCase(prop.Name, prop.Value);
        }
    }


    private void RenameToCamelCase(string name, JToken value)
    {
        var parent = value.Parent;
        if (parent == null)
            throw new InvalidOperationException("The parent is missing.");

        var newProperty = new JProperty(ToCamelCase(name), value);
        parent.Replace(newProperty);
    }

    private void RenameToPascalCase(string name, JToken value)
    {
        var parent = value.Parent;
        if (parent == null)
            throw new InvalidOperationException("The parent is missing.");

        var newProperty = new JProperty(ToPascalCase(name), value);
        parent.Replace(newProperty);
    }

    //Example: propertyName
    private string ToCamelCase(string value)
    {
        if (String.IsNullOrEmpty(value) || Char.IsLower(value, 0))
            return value;

        return Char.ToLowerInvariant(value[0]) + value.Substring(1);
    }

    //Example: PropertyName
    private string ToPascalCase(string value)
    {
        if (String.IsNullOrEmpty(value) || Char.IsUpper(value, 0))
            return value;

        return Char.ToUpperInvariant(value[0]) + value.Substring(1);
    }
}

Sample Use

[JsonConverter(typeof(ViewModelJsonConverter))]
public class TestClass {
    public string PropertyName { get; set; }
}

Upvotes: 0

Views: 583

Answers (2)

Brian Rogers
Brian Rogers

Reputation: 129827

If you're using Json.Net 9.0.1 or later, you can do what you want by using the NamingStrategyType parameter of the [JsonObject] attribute. So, in other words, just mark the classes you want to be camel cased like this:

[JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))]
public class TestClass
{
    ...
}

You don't need a ContractResolver or a custom JsonConverter.

Here is a round-trip demo:

public class Program
{
    public static void Main(string[] args)
    {
        TestClass tc = new TestClass
        {
            PropertyName = "foo",
            AnotherPropertyName = "bar"
        };

        Console.WriteLine("--- Serialize ---");
        string json = JsonConvert.SerializeObject(tc, Formatting.Indented);
        Console.WriteLine(json);
        Console.WriteLine();

        Console.WriteLine("--- Deserialize ---");
        TestClass test = JsonConvert.DeserializeObject<TestClass>(json);
        Console.WriteLine("PropertyName: " + test.PropertyName);
        Console.WriteLine("AnotherPropertyName: " + test.AnotherPropertyName);
    }
}

[JsonObject(NamingStrategyType = typeof(CamelCaseNamingStrategy))]
public class TestClass
{
    public string PropertyName { get; set; }
    public string AnotherPropertyName { get; set; }
}

Output:

--- Serialize ---
{
  "propertyName": "foo",
  "anotherPropertyName": "bar"
}

--- Deserialize ---
PropertyName: foo
AnotherPropertyName: bar

Upvotes: 1

Hung Cao
Hung Cao

Reputation: 3208

Have you ever tried any of these contract resolvers for newtonsoft json. For eg:

var jsonSerializerSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() };
var json = JsonConvert.SerializeObject(obj, Formatting.Indented, jsonSerializerSettings);

If you wanted to implement your own then please disregard.

Upvotes: 0

Related Questions