Reputation: 6826
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
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
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