【问题标题】:ViewModel Custom JsonConverterViewModel 自定义 JsonConverter
【发布时间】:2016-12-17 14:22:26
【问题描述】:

我正在尝试创建一个自定义 JsonConverter,它将 C# 属性名称更改为驼峰大小写,并将 javascript/json 属性名称更改为帕斯卡大小写。我觉得我在正确的轨道上,但我无法理解我需要做什么(而且我正处于时间紧缩状态)。

我意识到我可以将 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; }
}

【问题讨论】:

    标签: c# json json.net


    【解决方案1】:

    如果您使用的是 Json.Net 9.0.1 或更高版本,您可以使用 [JsonObject] 属性的 NamingStrategyType 参数来做您想做的事情。所以,换句话说,只需像这样标记你想要骆驼大小写的类:

    [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
    

    【讨论】:

      【解决方案2】:

      您是否曾经尝试过这些用于 newtonsoft json 的合约解析器。 例如:

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

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

      【讨论】:

      • 我不知道这一点,但我需要将它应用到特定的类。这似乎更像是一种全球性的变化。对吗?
      • 不,它发生在您调用序列化或反序列化方法之前。
      猜你喜欢
      • 1970-01-01
      • 2017-09-08
      • 2014-09-25
      • 2014-08-28
      • 2014-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多