custom serializer for just one property in Json.NET

Json序列化的时候跳过加密字段

字段类定义如下
  public class Field
    {
        public bool IsEncrypted { get; set; }

        public string Name { get; set; }

        public Object Value { get; set; }
    }

需要序列化User类

public class User
    {
        public Field UserName { get; set; }

        public Field Password { get; set; }
    }

序列化的结果,加密字段密码也被序列化出来了

复制代码
[Test]
        public void TestChuck()
        {
            User user = new User();
            Field field = new Field();
            field.IsEncrypted = false;
            field.Name = "UserName";
            field.Value = "chucklu";
            user.UserName = field;

            field = new Field();
            field.IsEncrypted = true;
            field.Name = "Password";
            field.Value = "123456";
            user.Password = field;

            string str = JsonConvert.SerializeObject(user);
            Console.WriteLine(str);
        }
复制代码

{
"UserName": {
"IsEncrypted": false,
"Name": "UserName",
"Value": "chucklu"
},
"Password": {
"IsEncrypted": true,
"Name": "Password",
"Value": "123456"
}
}

 

  

 https://stackoverflow.com/questions/18521970/custom-serializer-for-just-one-property-in-json-net 

You can add a custom serializer to a single attribute like this:

public class Comment
{
    public string Author { get; set; }

    [JsonConverter(typeof(NiceDateConverter))]
    public DateTime Date { get; set; }

    public string Text { get; set; }
}

public class NiceDateConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var date = value as DateTime;
        var niceLookingDate = date.ToString("MMMM dd, yyyy 'at' H:mm tt");
        writer.WriteValue(niceLookingDate);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException("Unnecessary because CanRead is false. The type will skip the converter.");
    }

    public override bool CanRead
    {
        get { return false; }
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(DateTime);
    }
}

Then, when you serialize your object with JsonConvert.SerializeObject(), the custom serializer will be used for the Date property.

 

解决方案

继承JsonConverter实现自定义的Converter,FieldConverter,然后在属性上添加[JsonConverter(typeof(FieldConverter))]

复制代码
 public class User
    {
        public Field UserName { get; set; }

        [JsonConverter(typeof(FieldConverter))]
        public Field Password { get; set; }
    }

    public class Field
    {
        public bool IsEncrypted { get; set; }

        public string Name { get; set; }

        public object Value { get; set; }
    }
复制代码

 

复制代码
  public class FieldConverter : JsonConverter
    {
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (value is Field field && !field.IsEncrypted)
            {
                var str = JsonConvert.SerializeObject(value);
                writer.WriteValue(str);
            }
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }

        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(Field);
        }
    }
复制代码

输出结果是

{
"UserName": {
"IsEncrypted": false,
"Name": "UserName",
"Value": "chucklu"
},
"Password": null
}

 

 类似的,如果Field 这样使用List<Field>

复制代码
 public class User
    {
        public List<Field> list = new List<Field>();
    }

    public class Field
    {
        public bool IsEncrypted { get; set; }

        public string Name { get; set; }

        public object Value { get; set; }
    }
复制代码
复制代码
  [Test]
        public void TestChuck()
        {
            User user = new User();
            Field field = new Field();
            field.IsEncrypted = false;
            field.Name = "UserName";
            field.Value = "chucklu";
            user.list.Add(field);

            field = new Field();
            field.IsEncrypted = true;
            field.Name = "Password";
            field.Value = "123456";
            user.list.Add(field);

            string str = JsonConvert.SerializeObject(user);
            Console.WriteLine(str);
        }
复制代码

输出是

{
"list": [
{
"IsEncrypted": false,
"Name": "UserName",
"Value": "chucklu"
},
{
"IsEncrypted": true,
"Name": "Password",
"Value": "123456"
}
]
}

 

 方案

唯一的问题是,把转义的双引号打出来了   使用 writer.WriteRawValue(str);可以避免json字符串被内部转义

复制代码
  public class FieldConverter : JsonConverter
    {
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            if (value is List<Field> list)
            {
                var temp = list.Where(x => !x.IsEncrypted).ToList();
                var str = JsonConvert.SerializeObject(temp);
                writer.WriteValue(str);
  writer.WriteRawValue(str); } }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { throw new NotImplementedException(); } public override bool CanConvert(Type objectType) { return objectType == typeof(List<Field>); } }
复制代码

 {"list":"[{\"IsEncrypted\":false,\"Name\":\"UserName\",\"Value\":\"chucklu\"}]"}   本来[]两边是没有双引号的,里面的转义也是多出来的

{"List":[{"IsEncrypted":false,"Name":"UserName","Value":"chucklu"}]} 必须是 writer.WriteRawValue(str);

如果是 writer.WriteRaw(str);的话,结果中会多出一个null

 

 

作者:Chuck Lu    GitHub    
posted @   ChuckLu  阅读(453)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
历史上的今天:
2018-06-19 NPOI设置Excel中的单元格识别为日期
2017-06-19 FileStream vs/differences StreamWriter?
2017-06-19 Excel显示当前日期
2015-06-19 编程概念--使用async和await的异步编程
2014-06-19 Winform中使用折叠窗口
点击右上角即可分享
微信分享提示