ViewModel自定义JsonConverter

时间:2016-12-16 21:41:03

标签: c# json json.net

我正在尝试创建一个自定义JsonConverter,它将C#属性名称更改为camel case和javascript / json属性名称为pascal case。我觉得我走在正确的轨道上,但我无法理解我需要做什么(而且我正处于紧张状态)。

我意识到我可以将JsonProperty属性添加到我的C#属性中,但我更愿意将属性应用于类而不是每个属性。

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);
    }
}

示例使用

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

2 个答案:

答案 0 :(得分:1)

如果您使用的是Json.Net 9.0.1或更高版本,则可以使用NamingStrategyType属性的[JsonObject]参数执行所需操作。所以,换句话说,只需标记你想成为像这样的类:

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

您不需要ContractResolver或自定义JsonConverter

这是一个往返演示:

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; }
}

输出:

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

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

答案 1 :(得分:0)

你有没有试过newtonsoft json的任何合约解析器。 例如:

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

如果你想实现自己的,请忽略。