zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    【OpenCV】几何失真校正与局部增强
    【C#】WinForm 之 DOTA2英雄搭配助手(网页抓取+在线绿色版+源码开放)
    【MFC】指纹类型识别(OpenCV + MATLAB混合编程)
    【MATLAB】图像细化算法
    【MATLAB】形态学变换
    【MATLAB】二值化效果
    一个女程序员的奋斗史
    数据结构之------C++指针冒泡排序算法
    C++之------进制学习
    串口屏之------Usart GPU 使用手册
  • 原文地址:https://www.cnblogs.com/chucklu/p/11050226.html
Copyright © 2011-2022 走看看