Newtonsoft.Json序列化与反序列化时使用不同的属性名

Newtonsoft.Json序列化与反序列化时使用不同的属性名称

    • 一、需求
    • 二、JsonProperty
    • 三、自定义Attribute
    • 四、自定义ContractResolver
    • 五、反序列化与序列化
    • 六、Readable与Writeable

一、需求

现有一个类IDCard

public class IDCard<T> : WordsResult
{
	public T address { get; set; }
	public T name { get; set; }
	public T birth { get; set; }
	public T idno { get; set; }
	public T gender { get; set; }
	public T nation { get; set; }
}

以及一段json字符串:

{"住址":"广东省深圳市福岗区笋岗西路30号","姓名":"栾韶","出生":"19660909","公民身份号码":"","性别":"男","民族":"回"}

我需要将字符串反序列化为IDCard对象,并且在一定的其它操作后再次将这个对象序列化后输出,同时输出的属性名用我自己定义的属性名。

我期望的输出结果:

{"address":"广东省深圳市福岗区笋岗西路30号","name":"栾韶","birth":"19660909","idno":"","gender":"男","nation":"回"}

二、JsonProperty

使用Newtonsoft.JsonJsonProperty特性

public class IDCard<T> : WordsResult
{
    [JsonProperty(propertyName: "住址")]
	public T address { get; set; }
    [JsonProperty(propertyName: "姓名")]
	public T name { get; set; }
    [JsonProperty(propertyName: "出生")]
	public T birth { get; set; }
    [JsonProperty(propertyName: "公民身份号码")]
	public T idno { get; set; }
    [JsonProperty(propertyName: "性别")]
	public T gender { get; set; }
    [JsonProperty(propertyName: "民族")]
	public T nation { get; set; }
}

反序列化时确实有效:
Newtonsoft.Json序列化与反序列化时使用不同的属性名_第1张图片

但重新将其序列化时:

{"住址":"广东省深圳市福岗区笋岗西路30号","姓名":"栾韶","出生":"19660909","公民身份号码":"","性别":"男","民族":"回"}

返回的并不是我期望的结果

三、自定义Attribute

定义Attribute类的派生类OcrAttribute

public class OcrAttribute : Attribute
{
    public string ReadName { get; set; }
    public string WriteName { get; set; }
    public bool Readable { get; set; }
    public bool Writable { get; set; }

    public OcrAttribute()
    {
        this.Readable = true;
        this.Writable = true;
    }
}

并添加到IDCard中:

public class IDCard<T> : WordsResult
{
    [Ocr(WriteName = "住址")]
    public T address { get; set; }

    [Ocr(WriteName = "姓名")]
    public T name { get; set; }

    [Ocr(WriteName = "出生")]
    public T birth { get; set; }

    [Ocr(WriteName = "公民身份号码")]
    public T idno { get; set; }

    [Ocr(WriteName = "性别")]
    public T gender { get; set; }

    [Ocr(WriteName = "民族")]
    public T nation { get; set; }
}

四、自定义ContractResolver

定义DefaultContractResolver的派生类,比如OcrWriteResolverOcrReadResolver

public class OcrWriteResolver: DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
        var attr = member.GetCustomAttribute(typeof(OcrAttribute)) as OcrAttribute;
        if (attr != null)
        {
            property.PropertyName = attr.WriteName ?? property.PropertyName;
            property.Writable = attr.Writable;
        }
        return property;
    }
}

public class OcrReadResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
        var attr = member.GetCustomAttribute(typeof(OcrAttribute)) as OcrAttribute;
        if (attr != null)
        {
            property.PropertyName = attr.ReadName ?? property.PropertyName;
            property.Readable = attr.Readable;
        }
        return property;
    }
}

重写CreateProperty方法,动态地修改JsonProperty的相关属性

五、反序列化与序列化

反序列化:

var settings = new JsonSerializerSettings() { ContractResolver = new OcrWriteResolver() };
var result = JsonConvert.DeserializeObject<IDCard<string>>(content);

序列化:

var settings = new JsonSerializerSettings() { ContractResolver = new OcrReadResolver() };
var str = JsonConvert.SerializeObject(result, settings);

Newtonsoft.Json序列化与反序列化时使用不同的属性名_第2张图片

六、Readable与Writeable

JsonProperty.Readable:属性是否可以被序列化
JsonProperty.Writeable:属性是否可以被反序列化

在某些特定场景下,比如:
从某个上级接口中返回了很多参数,在经过一系列处理后需要返回给下级接口其中一部分参数。

如果单纯为属性添加JsonIgnore特性,会导致我们在反序列化上级接口返回的json字符串时也无法获取到这个参数(比如上级平台返回的errcode我们不需要返回给下级平台,但是自身又需要根据这个属性来判断请求是否成功)。

OcrAttribute中新增WriteableReadable属性,并在OcrWriteResolverOcrReadResolverCreateProperty方法中动态修改property.Writableproperty.Readable

修改IDCard类,使得序列化时隐藏地址:

public class IDCard<T> : WordsResult
{
    [Ocr(WriteName = "住址", Readable = false)]
    public T address { get; set; }

    [Ocr(WriteName = "姓名")]
    public T name { get; set; }

    [Ocr(WriteName = "出生")]
    public T birth { get; set; }

    [Ocr(WriteName = "公民身份号码")]
    public T idno { get; set; }

    [Ocr(WriteName = "性别")]
    public T gender { get; set; }

    [Ocr(WriteName = "民族")]
    public T nation { get; set; }
}

进行序列化操作:
在这里插入图片描述
目的达成

你可能感兴趣的:(.net,c#,.net,json)