allbet开户:对 JsonConvert 的熟悉太肤浅了,终于照样遇到了问题

admin 1个月前 (08-11) 科技 31 1

一:靠山

1. 讲故事

在最先本文之前,真的好想做个问卷调查,到底有多少人和我一样,对 JSonConvert 的熟悉只局限在 SErializeObjectDeserializeObject 这两个方式上(┬_┬), 这样我也好结伴同行,不再孤独崎岖潦倒,或许是这两个方式基本上能够解决工作中 80% 的场景,对于我来说确实是这样,但随着编码的延续,终究照样会遇到那剩下的 20% ,以是呀。。。

我的场景是这样的:前段时间写营业代码的时刻,我有一个自界说的客户算法类型的Model,这个Model中有这种算法类型下的客户群以及Report统计息,还用了 HashSet 纪录了该类型下的 CustomerID聚集,为了利便讲述,我把Model简化如下:


    class CustomerALGorithmModel
    {
        public string DisplayName { get; set; }

        public int CustomerType { get; set; }

        public ReprotModel Report { get; set; }

        public HashSet<int> CustomerIDHash { get; set; }
    }

    class ReprotModel
    {
        public int TotalCustomerCount { get; set; }

        public int TotalTrADeCount { get; set; }
    }

那有意思的就来了,我小我私家是有记日志的癖好,就想着以后不会泛起死无对证的情形,然后就天经地义的使用 JsonConvert.SerializeObject, 这一下就出问题了,日志送入到了 ElasticSeARch ,然后通过 Kibana不出来,为啥呢? 看完上面的 Model 我想你也猜到了缘故原由,json体太大了哈,好歹 CustomerIDHash也有几十万个撒,这一下全导出成json了,这 size 还能小吗? 要不我写段代码看一看。


        static void MAIn(string[] args)
        {
            var algorithModel = new CustomerAlgorithmModel()
            {
                CustomerType = 1,
                DisplayName = "",
                Report = new ReprotModel()
                {
                    TotalCustomerCount = 1000,
                    TotalTradeCount = 50
                },
                CustomerIDHash = new HashSet<int>(Enumerable.Range(1, 500000))
            };

            var json = JsonConvert.SerializeObject(algorithModel);

            File.WriteAllText("1.TXT", json, Encoding.UTF8);

            CoNSole.WriteLine("写入完成!");
        }

可以看到,仅一个json就 3.3M,这样的纪录多来几打后,在 kibana 上一检索,浏览器就卡的要死,实在 CustomerIDHash 这个字段对我来说是无关紧要的,就算存下来了也没啥大用,以是需求就来了,若何屏蔽掉 CustomerIDHash

二:追求解决方案

1. 使用 JsonI.Nore

问题网上搜啊,这一搜马上就有人告诉你可以使用 JsonIGnoreAttribute 忽略特征,加好这个特征后继续跑一下程序。


    [Newtonsoft.Json.JsonIgnore]
    public HashSet<int> CustomerIDHash { get; set; }

太好了,终于搞定了,然则静下心来想一想,总感受心里有那么一点不舒服,为什么这么说,一旦你给这个 CustomerIDHash上了 JsonIgnore ,这就意味着它在 JsonConvet 的天下中今后消逝,也不管是谁在使用这个Model, 但这并不是我的初衷,我的初衷仅仅是为了在纪录日志的时刻踢掉 CustomerIDHash,可万万不要影响在其他场景下的使用哈,现在这种做法就会给自己,给别人挖坑,埋下了不能预知的bug,我想你应该明了我的意思,还得继续寻找下一个方案。

2. 使用自界说的 JsonConverter

真的,Newtonsoft 太壮大了,我都想写一个专题好好填补填补我的知识盲区,实在在这个场景中不就是想把 HashSet<int> 给屏蔽掉嘛,Newtonsoft 中专门提供了一个针对特定类型的自界说处置类,接下来我就写一段:


   /// <summary>
   /// 自界说一个 针对 HashSet<int> 的转换类
   /// </summary>
   public class HashSetConverter : Newtonsoft.Json.JsonConverter<HashSet<int>>
   {
       public override HashSet<int> ReadJson(JsonReader reader, Type objectType, HashSet<int> existingValue, bool hasExistingValue, JsonSerializer serializer)
       {
           return existingValue;
       }

       public override void WriteJson(JsonWriter writer, HashSet<int> value, JsonSerializer serializer)
       {
           writer.WriteNull();
       }
   } 

就是这么简朴,然后就可以在 SerializeObject 的时刻指定下自界说的 HashSetConverter 即可,然后再将程序跑起来看一下。


 var json = JsonConvert.SerializeObject(algorithModel, Formatting.Indented, new HashSetConverter());

从图中看,貌似也是解决了,但我突然发现自己要钻牛角尖了,若是我的实体中又来了一个顶级优质客户群的 TopNCustomerIDHash,但由于这个CustomerID 比较少,我希望在 Json 中能保留下来,然后就是踢掉的谁人 CustomerIDHash 我要保留 CustomerIDHash.Length ,哈哈,搞事情哈,那接下来怎么解决呢?

  • 修改 Model 实体

    class CustomerAlgorithmModel
    {
        public HashSet<int> CustomerIDHash { get; set; }

        // topN 优质客户群
        public HashSet<int> TopNCustomerIDHash { get; set; }
    }

  • HashSetConverter 增添逻辑判别是否为保留字段

        public override void WriteJson(JsonWriter writer, HashSet<int> value, JsonSerializer serializer)
        {
            if (writer.Path == "TopNCustomerIDHash")
            {
                writer.WriteStartArray();

                foreach (var item in value)
                {
                    writer.WriteValue(item);
                }

                writer.WriteEndArray();
            }
            else
            {
                writer.WriteValue(value.Count);
            }
        }

  • 最后给 TopNCustomerIDHash 赋值

            var algorithModel = new CustomerAlgorithmModel()
            {
                CustomerType = 1,
                DisplayName = "",
                Report = new ReprotModel()
                {
                    TotalCustomerCount = 1000,
                    TotalTradeCount = 50
                },
                CustomerIDHash = new HashSet<int>(Enumerable.Range(1, 500000)),
                TopNCustomerIDHash = new HashSet<int>(Enumerable.Range(1, 10)),
            };

三块都搞定后就可以把程序跑起来了,如下图:

Sunbet,进入申博Sunbet官网  第1张

貌似钻牛角尖的问题是解决了,既然钻牛角尖肯定要种种小看,好比这里的 ReportModel 我是不需要的,CustomerType 我也是不需要的,我仅仅需要看一下 DisplayNameTotalCustomerCount 这两个字段就可以了, 那这个要怎么解决呢?

3. 使用 匿名类型

确实许多时刻记日志,就是为了跟踪 Model 中你稀奇体贴的那几个字段,以是掺杂了多余的字段确实也是没必要的,这里可以用匿名来解决,我就来写一段代码:


    var json = JsonConvert.SerializeObject(new
    {
        algorithModel.DisplayName,
        algorithModel.Report.TotalCustomerCount
    }, Formatting.Indented);

Sunbet,进入申博Sunbet官网  第2张

三: 总结

虽然阻击了几个回合,但同时也发现了 Newtonsoft 中另有稀奇多的未挖掘功效,真的需要好好研究研究,源码已下好,接下来准备做个系列来剖解一下,值得一提的是 .Net中已自带了 System.Text.Json.JsonSerializer 类,现在来看功效还不算太厚实,简朴用用照样可以的,本篇就说到这里,希望对您有辅助。

如您有更多问题与我互动,扫描下方进来吧~

Sunbet,进入申博Sunbet官网  第3张,

allbet欧博真人客户端

欢迎进入allbet欧博真人客户端(Allbet Game):v,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务

Sunbet声明:该文看法仅代表作者自己,与本平台无关。转载请注明:allbet开户:对 JsonConvert 的熟悉太肤浅了,终于照样遇到了问题

网友评论

  • (*)

最新评论

站点信息

  • 文章总数:950
  • 页面总数:0
  • 分类总数:8
  • 标签总数:1967
  • 评论总数:52
  • 浏览总数:5308