A: background

1. Tell a story

Before starting this article, I really want to do a questionnaire, exactly how many people like me, the understanding of JsonConvert is only limited to SerializeObject and DeserializeObject these two methods (┬ _ ┬), so that I can go together. No longer lonely and down 😁😁😁, maybe these two methods can basically solve 80% of the scenarios at work, which is true for me, but as coding continues, you will eventually encounter the other 20%, so yay…

Here’s my scenario: Some time ago, when I was writing business code, I had a customized Model of customer algorithm type, which contained the customer base and Report statistics under this algorithm type, and also used HashSet to record the set of CustomerID under this type. For convenience, I simplified the Model as follows:

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; }}Copy the code

The interesting came, I personally have logs nut, just won’t appear dead men tell no tales, then of course use JsonConvert. SerializeObject, it is a problem, log into the ElasticSearch, I couldn’t find it through Kibana. Why? After looking at the Model above, I think you can guess the reason. The JSON body is too big. At least there are hundreds of thousands of sashes in CustomerIDHash, which are all exported into JSON. Maybe I’ll write some code and look at it.

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(" Write complete!" ); }Copy the code

As you can see, a single JSON is 3.3m. After a few dozen of these records are retrieved on Kibana, the browser will be dead. In fact, the CustomerIDHash field is not necessary for me, even if it is saved, it is not very useful, so the demand comes. How to disable CustomerIDHash.

Two: seek solutions

1. Use JsonIgnore

If you have any questions, do a web search, and immediately someone tells you that you can use the JsonIgnoreAttribute ignore feature, add that feature and continue running the program.


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

That’s great, I’m done, but when I think about it, I feel a little bit uncomfortable. Once you put JsonIgnore on this CustomerIDHash, it means it’s gone from the world of JsonConvet. No matter who is using the Model, this is not my original intention. My original intention is only to kick the CustomerIDHash when logging. Please do not affect the use of CustomerIDHash in other scenarios. I think you know what I mean. We have to keep looking for the next solution.

2. Use custom JsonConverter

Newtonsoft is so powerful that I want to write a special topic to fill in my knowledge blind spot. In this case, I want to mask the HashSet

. Newtonsoft provides a custom class for specific types of processing.

// </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();  }}Copy the code

That’s it. Then you can specify a custom HashSetConverter in SerializeObject and run the program.


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

From the picture, it seems to be solved, but I suddenly found myself in a corner. If my entity has another TopNCustomerIDHash of a top quality customer base, but this CustomerID is relatively small, I hope to keep it in Json. I’m going to keep the CustomerIDHash.Length. I’m going to keep the CustomerIDHash.

  • Modify the Model entity
class CustomerAlgorithmModel { public HashSet<int> CustomerIDHash { get; set; } public HashSet<int> TopNCustomerIDHash {get; set; }}Copy the code
  • HashSetConverter adds logic to identify whether a field is reserved
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); }}Copy the code
  • Finally, assign TopNCustomerIDHash
Var algorithModel = new CustomerModel () {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)), };Copy the code

Once all three pieces are done, the program is ready to run, as shown below:

It seems that the problem has been solved. Since the problem must be despised, for example, I don’t need ReportModel and CustomerType. I just need to look at the DisplayName and TotalCustomerCount fields, so how do I solve this?

3. Use anonymous types

Most of the time, logging is to keep track of the fields in the Model that you care about most, so there is no need to add extra fields.


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

Three:

Although I blocked several rounds, I also found that there are many unexplored functions in Newtonsoft. I really need to study them carefully. The source code has been prepared. It is worth mentioning the.net has built-in System. In the Text. The Json. The JsonSerializer class, now function isn’t too rich, simple to use or can be, this is here, I hope it can help you.