添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
聪明伶俐的单杠  ·  C++ String(字符串)和 ...·  7 小时前    · 
直爽的电脑桌  ·  C++ 中 char 与 string ...·  7 小时前    · 
捣蛋的手术刀  ·  C#: Swapping ...·  4 小时前    · 
买醉的吐司  ·  USAJOBS - Search·  1 周前    · 
追风的鼠标  ·  【转】在'git ...·  3 月前    · 
礼貌的跑步机  ·  Tenable Community·  5 月前    · 
I’ve used Newtonsoft’s Json.NET since as far back as I can remember. It is a fantastic package for working with objects and JSON. When .NET’s own Text.Json namespace was release in 2019, I -like many- largely ignored it. There just wasn’t a need to switch to the new package and many of our other packages had a dependency for Json.NET anyway.

In 2021, I was upgrading an old project to .NET 5 and felt that the time was right for the move to Text.Json.

I have no doubt that there are countless articles around, comparing the performance between the two packages. My goal was just to reduce the number of third-party package dependencies.

Is the serialised JSON produced the same? Is the code very different?

This is what I found.

Is the code very different?

In short, no.

Employee employee1 = new Employee();
string json;
// newtonsoft
json = Newtonsoft.Json.JsonConvert.SerializeObject(employee1);
employee1 = Newtonsoft.Json.JsonConvert.DeserializeObject<Employee>(json);
// text-json
json = System.Text.Json.JsonSerializer.Serialize(employee1);
employee1 = System.Text.Json.JsonSerializer.Deserialize<Employee>(json);

But also, yes, more about this later.

Is the JSON the same?

Yes, sort of but actually, no.

I serialised the same object with a number of common-typed properties. The results were identical with both packages.

public class Employee
  public Guid ID { get; set; } = Guid.NewGuid();
  public string Name { get; set; } = "Anders Anderson";
  public DateTime DateOfBirth { get; set; } = new DateTime(2000, 1, 1);
  public int TelExt { get; set; } = 101;
  public KeyValuePair<int, int> Seat1 { get; set; } = new KeyValuePair<int, int>(0, 0);
  public Tuple<int, int> Seat2 { get; set; } = new Tuple<int, int>(0, 0);
//{ID:e2064746-8dbf-4e1f-bba6-cb38c41fbdd7,Name:Anders Anderson,DateOfBirth:2000-01-01T00:00:00,TelExt:101,Seat1:{Key:0,Value:0},Seat2:{Item1:0,Item2:0}}

When I tested with some types from the System.Drawing namespace, the results were unfortunately different.

public class Employee
  public Point Office { get; set; } = new Point(0, 0);        
  public Size Workspace { get; set; } = new Size(2, 1);
// newtonsoft
//{"Office":"0, 0","Workspace":"2, 1"}
// text-json
//{"Office":{"IsEmpty":true,"X":0,"Y":0},"Workspace":{"IsEmpty":false,"Width":2,"Height":1}}

Using user-defined converters

To retain backwards-compatibility for JSON created by Json.NET, we can define converters to customise how objects are serialised (and deserialised).

public class JsonPointConverter : JsonConverter
  public override Point Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    Point result = new Point(0, 0);
    if (reader.TokenType == JsonTokenType.String)
      string[] array = reader.GetString()!.Split(',');
      if (array.Length != 2)
        return result;
      int result2 = 0;
      int result3 = 0;
      if (!int.TryParse(array[0].Trim(), out result2))
        result2 = 0;
      if (!int.TryParse(array[1].Trim(), out result3))
        result3 = 0;
      return new Point(result2, result3);
    return result;
  public override void Write(Utf8JsonWriter writer, Point value, JsonSerializerOptions options)
    writer.WriteStringValue($"{value.X.ToString()}, {value.Y.ToString()}");
public class JsonSizeConverter : JsonConverter
  public override Size Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    Size result = new Size(0, 0);
    if (reader.TokenType == JsonTokenType.String)
      string[] array = reader.GetString()!.Split(',');
      if (array.Length != 2)
        return result;
      int result2 = 0;
      int result3 = 0;
      if (!int.TryParse(array[0].Trim(), out result2))
        result2 = 0;
      if (!int.TryParse(array[1].Trim(), out result3))
        result3 = 0;
      return new Size(result2, result3);
    return result;
  public override void Write(Utf8JsonWriter writer, Size value, JsonSerializerOptions options)
    writer.WriteStringValue($"{value.Width.ToString()}, {value.Height.ToString()}");

The converters above simplify the Point and Size types in a way that I thought would be obvious.

The implementation would be like this.

Employee employee1 = new Employee();
var options = new JsonSerializerOptions();
options.Converters.Add(new JsonPointConverter());
options.Converters.Add(new JsonSizeConverter());
string json = System.Text.Json.JsonSerializer.Serialize(employee1, options);
employee1 = System.Text.Json.JsonSerializer.Deserialize<Employee>(json, options);

And one last thing.

I encountered an unexpected problem when I had special characters in the JSON. Json.NET would escape the characters using the traditional slash (“\”) but Text.Json would encode the characters as unicode. This shouldn’t be a problem except that not a single JSON editor I found works that way. I end up with the unicode characters being stripped out.

public class Employee
  public string Name { get; set; } = "Anders \"Andy\" Anderson";
// newtonsoft
//{"Name":"Anders \"Andy\" Anderson"}
// text-json
//{"Name":"Anders \u0022Andy\u0022 Anderson"}

Lucky, this is an easy fix in the options.

var options = new JsonSerializerOptions();
options.Converters.Add(new JsonPointConverter());
options.Converters.Add(new JsonSizeConverter());
options.Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
string json = System.Text.Json.JsonSerializer.Serialize(employee1, options);
employee1 = System.Text.Json.JsonSerializer.Deserialize<Employee>(json, options);

Well, that’s that.

I hope someone finds this useful.

Social Media

 Share Tweet

Categories

Programming

.NET C#

Post Information

Posted on Sat 12th Mar 2022

Modified on Sat 5th Aug 2023