One: Tell stories

The 6 features introduced in the last post have worked well in the garden, so here are 6 more to enjoy.

Two: characteristic analysis

1. Parse JSON like a weakly typed language

We all know that there are many weakly typed languages, such as Nodejs, Python, and PHP. One of their 🐮👃 places is to handle JSON, which does not require a class as strongly typed languages do. Let’s take the JSON down here.

{"DisplayName": "new generation algorithm model ", "CustomerType": 1, "Report": {"TotalCustomerCount": 1000, "TotalTradeCount": 50}, "CustomerIDHash": [1,2,3,4,5]}Copy the code

If you want this json to be processed in C#, you need to define a suitable class for it, just like the client algorithm model class in the first article. Ha ha, of course, can be deserialized into the Dictionary, and then take extract Report. TotalCustomerCount and CustomerIDHash demonstrate these two fields.

Static void Main(string[] args) {var json = @"{'DisplayName': 'new algorithm ', 'CustomerType': 1, 'Report': {'TotalCustomerCount': 1000, 'TotalTradeCount': 50}, 'CustomerIDHash': [1,2,3,4,5]}"; var dict = JsonConvert.DeserializeObject<Dictionary<object, object>>(json); var report = dict["Report"] as JObject; var totalCustomerCount = report["TotalCustomerCount"]; Console.WriteLine($"totalCustomerCount={totalCustomerCount}"); var arr = dict["CustomerIDHash"] as JArray; var list = arr.Select(m => m.Value<int>()).ToList(); Console.WriteLine($"list={string.Join(",", list)}"); }Copy the code

2. How do I keep enumerations in JSON as strings that are more readable

What does that mean? By default, SerializeObject changes the Enum in Model to numeric, which is notoriously semantic, as shown in the following code:

static void Main(string[] args) { var model = new ThreadModel() { ThreadStateEnum = System.Threading.ThreadState.Running }; var json = JsonConvert.SerializeObject(model); Console.WriteLine(json); } class ThreadModel { public System.Threading.ThreadState ThreadStateEnum { get; set; }}Copy the code

Right? The semantics are really bad, so can we just generate Running? Of course… The transformation is as follows:


  var json = JsonConvert.SerializeObject(model, new StringEnumConverter());
Copy the code

JsonConverter = JsonConverter = JsonConverter = JsonConverter = JsonConverter = JsonConverter = JsonConverter

static void Main(string[] args) { var model = new ThreadModel() { ThreadStateEnum = System.Threading.ThreadState.Running, TaskStatusEnum = TaskStatus.RanToCompletion }; var json = JsonConvert.SerializeObject(model); Console.WriteLine(json); } class ThreadModel { public System.Threading.ThreadState ThreadStateEnum { get; set; } [JsonConverter(typeof(StringEnumConverter))] public TaskStatus TaskStatusEnum { get; set; }}Copy the code

3. Format the time type in the JSON file

When converting a model to JSON, there is always a time type. To make the time type more readable, it is usually formatted as YYYY /MM/DD day. JsonConvert is also an enumeration to help you out…

The static void Main (string [] args) {var json = JsonConvert. SerializeObject (new Order () {OrderTitle = "female bosses", Created = datetime. Now}, new JsonSerializerSettings {DateFormatString = "YYYY ",}); Console.WriteLine(json); } public class Order { public string OrderTitle { get; set; } public DateTime Created { get; set; }}Copy the code

By the way, I remember a long time ago when C# came with a JavaScriptSerializer that was also used to convert a datetime into a timestamp instead of a time string. If you have special reason to time generated by JsonConvert timestamp, also can, with DateFormatHandling. MicrosoftDateFormat enumeration specifies the can, as follows:

4. Globalize some common Settings

All of the previous feature techniques demonstrated were specified on JsonConvert, that is, 100 JsonConvert I have to specify 100 times. Is there a similar specification that applies to the entire process? Newtonsoft has long supported such a powerful Order, take the above example:

JsonConvert.DefaultSettings = () => { var settings = new JsonSerializerSettings { Formatting = Formatting.Indented }; return settings; }; Var order = new order () {OrderTitle = "new order ", Created = datetime.now}; var json1 = JsonConvert.SerializeObject(order); var json2 = JsonConvert.SerializeObject(order); Console.WriteLine(json1); Console.WriteLine(json2);Copy the code

As you can see, runing.Indented works for both strings of JSON.

5. How to ensure the rigor of JSON to model and extract JSON unknown fields

Sometimes we have a requirement that if an unknown field appears in the JSON model, there are two options: either to report an error or to extract the unknown field. Newtonsoft default is to ignore the field, so you can find the scene yourself.

  • An error occurred in the unknown field
Static void Main(string[] args) {var json = "{'OrderTitle':' womenid ',' Created':'2020/6/23','Memo':' Order note '}"; var order = JsonConvert.DeserializeObject<Order>(json, new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Error }); Console.WriteLine(order); } public class Order { public string OrderTitle { get; set; } public DateTime Created { get; set; } public override string ToString() { return $"OrderTitle={OrderTitle}, Created={Created}"; }}Copy the code

  • Extracting unknown fields

I vaguely remember that WCF also uses an ExtenstionDataObject in this scenario to store the unknown fields sent from the client. It may be that the client’s Model has been updated, and the server is still the old version. This situation is also commonly encountered in JSON serialization. In JsonConvert, you can use _additionalData to help you get it. In OnDeserialized, AOP method, you can intercept it as follows:

Static void Main(string[] args) {var json = "{'OrderTitle':' womenid ',' Created':'2020/6/23','Memo':' Order note '}"; var order = JsonConvert.DeserializeObject<Order>(json); Console.WriteLine(order); } public class Order { public string OrderTitle { get; set; } public DateTime Created { get; set; } [JsonExtensionData] private IDictionary<string, JToken> _additionalData; public Order() { _additionalData = new Dictionary<string, JToken>(); } [OnDeserialized] private void OnDeserialized(StreamingContext context) { var dict = _additionalData; } public override string ToString() { return $"OrderTitle={OrderTitle}, Created={Created}"; }}Copy the code

6. Enable JsonConvert detailed logs

Sometimes it’s better to have logging on when you’re looking at the source code, so it’s also a very useful feature. See how to configure it.

Static void Main(string[] args) {var json = "{'OrderTitle':' womenid ',' Created':'2020/6/23','Memo':' Order note '}"; MemoryTraceWriter traceWriter = new MemoryTraceWriter(); var account = JsonConvert.DeserializeObject<Order>(json, new JsonSerializerSettings { TraceWriter = traceWriter }); Console.WriteLine(traceWriter.ToString()); } public class Order { public string OrderTitle { get; set; } public DateTime Created { get; set; } public override string ToString() { return $"OrderTitle={OrderTitle}, Created={Created}"; }}Copy the code

Three:

Hey hey, this article 6 features even said, combined with a total of 12 features, is not very simple and practical, ready to bring you some source code interpretation! Hope this article is helpful to you, thank you!