现有一个类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":"回"}
使用Newtonsoft.Json的JsonProperty特性
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; }
}
但重新将其序列化时:
{"住址":"广东省深圳市福岗区笋岗西路30号","姓名":"栾韶","出生":"19660909","公民身份号码":"","性别":"男","民族":"回"}
返回的并不是我期望的结果
定义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; }
}
定义DefaultContractResolver的派生类,比如OcrWriteResolver和OcrReadResolver:
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);
JsonProperty.Readable:属性是否可以被序列化
JsonProperty.Writeable:属性是否可以被反序列化
在某些特定场景下,比如:
从某个上级接口中返回了很多参数,在经过一系列处理后需要返回给下级接口其中一部分参数。
如果单纯为属性添加JsonIgnore特性,会导致我们在反序列化上级接口返回的json字符串时也无法获取到这个参数(比如上级平台返回的errcode我们不需要返回给下级平台,但是自身又需要根据这个属性来判断请求是否成功)。
在OcrAttribute中新增Writeable与Readable属性,并在OcrWriteResolver与OcrReadResolver的CreateProperty方法中动态修改property.Writable与property.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; }
}