NewtonSoft JsonConverter-将属性重命名为其他属性的值

行尸走肉

我有这个课:

public class ValueInteger
{
    [JsonIgnore]
    public string ValueName { get; set; }

    public int Value { get; set; }

    [JsonProperty("timestamp")]
    public UInt64 TimeStamp { get; set; }

}

给定一个实例:

var valueInt = new ValueInteger 
    { 
        ValueName = "mycounter",
        Value = 7,
        TimeStamp = 1010101010
    }

它应该序列化为:

{ mycounter: 7, timestamp = 1010101010 }

如果可以将Value属性声明为

    [JsonRedirect(titlePropertyName: nameof(ValueName))]
    public int Value { get; set; }

我可能必须实现自己的ContractResolver,并研究以下内容:https ://stackoverflow.com/a/47872645/304820,但这取决于IValueProvider和AFAIK,没有用于重命名的INameProvider。

通常,重命名是按类而不是按实例进行的。

安德斯·卡斯滕森

我的解决方法是编写自己的Converter。转换器仅以与普通转换器相同的方式进行序列化,但是只要遇到属性上的特殊属性,都应在输出中重命名该属性。

因此,序列化C#对象将如下所示:

  1. 首先将C#对象转换为JSON对象(即JTokens结构)。
  2. 运行C#对象中的属性,找到需要重命名的属性。
  3. 对于这些属性中的每一个,请确定其当前名称是什么以及其新名称应该是什么。
  4. 对JSON对象执行重命名。
  5. 最后将JSON对象序列化为字符串。

我对此做了一个简单的实现。用法如下所示:

class Program
{
    static void Main(string[] args)
    {
        var valueInt = new ValueInteger
        {
            ValueName = "mycounter",
            Value = 7,
            TimeStamp = 1010101010
        };

        var settings = new JsonSerializerSettings { Converters = new JsonConverter[] { new DynamicNameConverter() } };
        var result = JsonConvert.SerializeObject(valueInt, settings);
        Console.WriteLine(result);
        Console.Read();
    }
}


public class ValueInteger
{
    [JsonIgnore]
    public string ValueName { get; set; }

    [JsonDynamicName(nameof(ValueName))]
    public int Value { get; set; }

    [JsonProperty("timestamp")]
    public UInt64 TimeStamp { get; set; }
}

和助手类:

class DynamicNameConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        // Only use this converter for classes that contain properties with an JsonDynamicNameAttribute.
        return objectType.IsClass && objectType.GetProperties().Any(prop => prop.CustomAttributes.Any(attr => attr.AttributeType == typeof(JsonDynamicNameAttribute)));
    }

    public override bool CanRead => false;
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // We do not support deserialization.
        throw new NotImplementedException();
    }

    public override bool CanWrite => true;
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var token = JToken.FromObject(value);
        if (token.Type != JTokenType.Object)
        {
            // We should never reach this point because CanConvert() only allows objects with JsonPropertyDynamicNameAttribute to pass through.
            throw new Exception("Token to be serialized was unexpectedly not an object.");
        }

        JObject o = (JObject)token;
        var propertiesWithDynamicNameAttribute = value.GetType().GetProperties().Where(
            prop => prop.CustomAttributes.Any(attr => attr.AttributeType == typeof(JsonDynamicNameAttribute))
        );

        foreach (var property in propertiesWithDynamicNameAttribute)
        {
            var dynamicAttributeData = property.CustomAttributes.FirstOrDefault(attr => attr.AttributeType == typeof(JsonDynamicNameAttribute));

            // Determine what we should rename the property from and to.
            var currentName = property.Name;
            var propertyNameContainingNewName = (string)dynamicAttributeData.ConstructorArguments[0].Value;
            var newName = (string)value.GetType().GetProperty(propertyNameContainingNewName).GetValue(value);

            // Perform the renaming in the JSON object.
            var currentJsonPropertyValue = o[currentName];
            var newJsonProperty = new JProperty(newName, currentJsonPropertyValue);
            currentJsonPropertyValue.Parent.Replace(newJsonProperty);
        }

        token.WriteTo(writer);
    }
}

[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
class JsonDynamicNameAttribute : Attribute
{
    public string ObjectPropertyName { get; }
    public JsonDynamicNameAttribute(string objectPropertyName)
    {
        ObjectPropertyName = objectPropertyName;
    }
}

请注意,可能会引入很多错误处理,DynamicNameConverter但是为了简化阅读和理解,我省略了它。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

将“发布”重命名为其他内容

NewtonSoft.Json自定义JsonConverter反序列化为DateTime不起作用

属性的自定义JsonConverter:获取属性名称

在没有属性的类上全局使用JsonConverter

NewtonSoft JsonConverter-访问其他属性

JsonConverter不能用作属性属性

Newtonsoft.Json DeserializedObject错误的属性值

将所有其他级别重命名为“其他”

在类属性上使用JsonConverter时选择NamingStrategy

使用属性属性定义要使用的JsonConverter

Newtonsoft Json.NET JsonConverter属性在反序列化时保留引用问题

自定义Newtonsoft JsonConverter,用于数组和集合,以进行进一步操作

自定义JsonConverter属性无法在ASP.NET Core 3.1中使用Newtonsoft.JSON与Json.Serialize()一起使用

从JsonConverter.ReadJson访问已反序列化的属性

如何覆盖默认的JsonConverter(在属性中指定)

使用Newtonsoft创建自定义JsonConverter时尊重JsonSerializer设置

Newtonsoft JsonConverter将字符串或对象转换为对象

Newtonsoft JSON重命名属性名称取决于另一个属性

C#NewtonSoft单个对象或数组JsonConverter不起作用,没有错误

使用[JsonConverter]属性时,我的JsonConverter类中的StackOverflowException

jsonconverter Web api datetime属性获得01/01/0001

BASH脚本将XML文件重命名为属性值

将JsonConverter分配给类而不使用属性

如何捕获在JsonConverter属性中引发的异常?

在自定义Newtonsoft JsonConverter类中访问dbcontext

NewtonSoft JsonConverter 构造函数参数

用 NewtonSoft 替换 Json 属性

Newtonsoft 重命名扩展方法以重命名 JObject .net 中的属性名称

为什么 JsonConverter 属性不是从接口继承的?