c#:System.Text.Json 的使用一

环境:

  • .net 6.0
  • vs2022

参考:
从 Newtonsoft.Json 迁移到 System.Text.Json
System.Text.Json 常规用法

一、写入时的控制

1.1 非ascii码转换

直接看代码:

var str = System.Text.Json.JsonSerializer.Serialize(new Model {
    
     Id = 1, Name = "小明" });
Console.WriteLine(str);
//out: {"Id":1,"Name":"\u5C0F\u660E"}

public class Model
{
    
    
    public int Id {
    
     get; set; }
    public string Name {
    
     get; set; }
}

为了能输出 “小明” 而不是 “\u5C0F\u660E”,我们需要显示声明编码方法:

var str = System.Text.Json.JsonSerializer.Serialize(new Model {
    
     Id = 1, Name = "小明" }, new System.Text.Json.JsonSerializerOptions
{
    
    
    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
});
//out: {"Id":1,"Name":"小明"}
public class Model
{
    
    
    public int Id {
    
     get; set; }
    public string Name {
    
     get; set; }
}

比对:Newtonsoft.Json 默认就是 “小明”

1.2 首字母小写

默认类属性和dictionary的key都是原样输出,如:

var str = System.Text.Json.JsonSerializer.Serialize(new Model
{
    
    
    Id = 1,
    Name = "小明",
    Properties = new Dictionary<string, object> {
    
     {
    
     "Age", 18 }, {
    
     "Other", new {
    
     Name = "小刚" } } }
}, new System.Text.Json.JsonSerializerOptions
{
    
    
    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
});
Console.WriteLine(str);
//out: {"Id":1,"Name":"小明","Properties":{"Age":18,"Other":{"Name":"小刚"}}}

public class Model
{
    
    
    public int Id {
    
     get; set; }
    public string Name {
    
     get; set; }
    public Dictionary<string, object> Properties {
    
     get; set; }
}

如果想首字母小写,则:

var str = System.Text.Json.JsonSerializer.Serialize(new Model
{
    
    
    Id = 1,
    Name = "小明",
    Properties = new Dictionary<string, object> {
    
     {
    
     "Age", 18 }, {
    
     "Other", new {
    
     Name = "小刚" } } }
}, new System.Text.Json.JsonSerializerOptions
{
    
    
    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
    //属性名首字母小写
    PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase,
    //字典key首字母小写
    DictionaryKeyPolicy = System.Text.Json.JsonNamingPolicy.CamelCase,
});
Console.WriteLine(str);
//out: {"id":1,"name":"小明","properties":{"age":18,"other":{"name":"小刚"}}}

public class Model
{
    
    
    public int Id {
    
     get; set; }
    public string Name {
    
     get; set; }
    public Dictionary<string, object> Properties {
    
     get; set; }
}

比对:Newtonsoft.Json 默认也是原样,也可以控制属性首字母小写(但未找到控制字典key首字母小写的方法)

1.3 缩进格式输出

默认输出是一行(上面的效果),可以指定缩进输出,如下:

var str = System.Text.Json.JsonSerializer.Serialize(new Model
{
    
    
    Id = 1,
    Name = "小明",
    Properties = new Dictionary<string, object> {
    
     {
    
     "Age", 18 }, {
    
     "Other", new {
    
     Name = "小刚" } } }
}, new System.Text.Json.JsonSerializerOptions
{
    
    
    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
    //缩进输出
    WriteIndented = true,
});
Console.WriteLine(str);
/* out:
{
  "Id": 1,
  "Name": "小明",
  "Properties": {
    "Age": 18,
    "Other": {
      "Name": "小刚"
    }
  }
}
*/

public class Model
{
    
    
    public int Id {
    
     get; set; }
    public string Name {
    
     get; set; }
    public Dictionary<string, object> Properties {
    
     get; set; }
}

比对:Newtonsoft.Json 默认也是一行,也可以控制缩进

1.4 将枚举转成字符串输出

默认枚举转为数字输出,如下:

扫描二维码关注公众号,回复: 15197769 查看本文章
var str = System.Text.Json.JsonSerializer.Serialize(new Model
{
    
    
    Id = 1,
    Name = "小明",
    Sex = EnumSex.Male,
}, new System.Text.Json.JsonSerializerOptions
{
    
    
    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
});
Console.WriteLine(str);
//out: {"Id":1,"Name":"小明","Sex":0}

public class Model
{
    
    
    public int Id {
    
     get; set; }
    public string Name {
    
     get; set; }
    public EnumSex Sex {
    
     get; set; }
}
public enum EnumSex
{
    
    
    Male,
    FeMale
}

可以添加转换器来转换成字符串:

var options = new System.Text.Json.JsonSerializerOptions
{
    
    
    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
};
options.Converters.Add(new System.Text.Json.Serialization.JsonStringEnumConverter());
var str = System.Text.Json.JsonSerializer.Serialize(new Model
{
    
    
    Id = 1,
    Name = "小明",
    Sex = EnumSex.Male,
}, options);
Console.WriteLine(str);
//out: {"Id":1,"Name":"小明","Sex":"Male"}

public class Model
{
    
    
    public int Id {
    
     get; set; }
    public string Name {
    
     get; set; }
    public EnumSex Sex {
    
     get; set; }
}
public enum EnumSex
{
    
    
    Male,
    FeMale
}

比对:Newtonsoft.Json 默认也是转为数字,也可以控制转为字符串

1.5 忽略null值属性的输出

默认情况下,如果某个属性值为null,也会被输出,如下:

var options = new System.Text.Json.JsonSerializerOptions
{
    
    
    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
var str = System.Text.Json.JsonSerializer.Serialize(new Model
{
    
    
    Id = 1,
    Name = null
}, options);
Console.WriteLine(str);
//out: {"Id":1,"Name":null}

public class Model
{
    
    
    public int Id {
    
     get; set; }
    public string Name {
    
     get; set; }
}

如果不想输出null值属性,如下:

var options = new System.Text.Json.JsonSerializerOptions
{
    
    
    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
    DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull,
};
var str = System.Text.Json.JsonSerializer.Serialize(new Model
{
    
    
    Id = 1,
    Name = null
}, options);
Console.WriteLine(str);
//out: {"Id":1}

public class Model
{
    
    
    public int Id {
    
     get; set; }
    public string Name {
    
     get; set; }
}

比对:Newtonsoft.Json 默认也是输出null值属性,也可以控制不输出

1.6 忽略循环引用

默认情况下,system.text.json会直接报错,如下:

var options = new System.Text.Json.JsonSerializerOptions
{
    
    
    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
};
var fu = new Model
{
    
    
    Id = 1,
    Name = "小明",
    Parent = null,
    Children = new List<Model> {
    
     new Model {
    
     Id = 2, Name = "小明2", Parent = null } }
};
fu.Children[0].Parent = fu;
var str = System.Text.Json.JsonSerializer.Serialize(fu, options);
Console.WriteLine(str);
/*expception:
Unhandled exception. System.Text.Json.JsonException: A possible object cycle was detected. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 64. Consider using ReferenceHandler.Preserve on JsonSerializerOptions to support cycles. Path: $.Children.Parent.Children.Parent
*/


public class Model
{
    
    
    public int Id {
    
     get; set; }
    public string Name {
    
     get; set; }
    public Model Parent {
    
     get; set; }
    public List<Model> Children {
    
     get; set; }
}

我们可以设置忽略循环引用,如下:

var options = new System.Text.Json.JsonSerializerOptions
{
    
    
    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
    //忽略循环引用
    ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.IgnoreCycles,
};
var fu = new Model
{
    
    
    Id = 1,
    Name = "小明",
    Parent = null,
    Children = new List<Model> {
    
     new Model {
    
     Id = 2, Name = "小明2", Parent = null } }
};
fu.Children[0].Parent = fu;
var str = System.Text.Json.JsonSerializer.Serialize(fu, options);
Console.WriteLine(str);
//out: {"Id":1,"Name":"小明","Parent":null,"Children":[{"Id":2,"Name":"小明2","Parent":null,"Children":null}]}

public class Model
{
    
    
    public int Id {
    
     get; set; }
    public string Name {
    
     get; set; }
    public Model Parent {
    
     get; set; }
    public List<Model> Children {
    
     get; set; }
}

比对:Newtonsoft.Json 默认也是检测到循环报错,也可以控制忽略循环引用

1.7 允许输出Field

默认情况下,Field不会被输出,如下:

var options = new System.Text.Json.JsonSerializerOptions
{
    
    
    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
};
var str = System.Text.Json.JsonSerializer.Serialize(new Model
{
    
    
    Id = 1,
    Name = "小明",
    FieldAge = 18,
}, options);
Console.WriteLine(str);
//out: {"Id":1,"Name":"小明"}

public class Model
{
    
    
    public int Id {
    
     get; set; }
    public string Name {
    
     get; set; }
    public int FieldAge;
}

为了输出Field,如下:

var options = new System.Text.Json.JsonSerializerOptions
{
    
    
    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
    // 输出 Field
    IncludeFields = true,
};
var str = System.Text.Json.JsonSerializer.Serialize(new Model
{
    
    
    Id = 1,
    Name = "小明",
    FieldAge = 18,
}, options);
Console.WriteLine(str);
//out: {
    
    {"Id":1,"Name":"小明","FieldAge":18}


public class Model
{
    
    
    public int Id {
    
     get; set; }
    public string Name {
    
     get; set; }
    public int FieldAge;
}

比对:Newtonsoft.Json 默认输出Field,并且只读Field也会输出,这点需要注意!

1.8 禁止输出只读Field

当我们允许输出Field的时候,只读的Field也会被输出,如下:

var options = new System.Text.Json.JsonSerializerOptions
{
    
    
    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
    //允许输出Field
    IncludeFields = true,
};
var str = System.Text.Json.JsonSerializer.Serialize(new Model
{
    
    
    Id = 1,
    Name = "小明",
    FieldAge = 18,
}, options);
Console.WriteLine(str);
//out: {"Id":1,"Name":"小明","FieldAge":18,"ReadOnlyFieldAge":15}


public class Model
{
    
    
    public int Id {
    
     get; set; }
    public string Name {
    
     get; set; }
    public int FieldAge;
    public readonly int ReadOnlyFieldAge = 15;
}

如果我们不想输出只读的Field,如下:

var options = new System.Text.Json.JsonSerializerOptions
{
    
    
    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
    //允许输出Field
    IncludeFields = true,
    //忽略只读Field
    IgnoreReadOnlyFields = true,
};
var str = System.Text.Json.JsonSerializer.Serialize(new Model
{
    
    
    Id = 1,
    Name = "小明",
    FieldAge = 18,
}, options);
Console.WriteLine(str);
//out: {"Id":1,"Name":"小明","FieldAge":18}


public class Model
{
    
    
    public int Id {
    
     get; set; }
    public string Name {
    
     get; set; }
    public int FieldAge;
    public readonly int ReadOnlyFieldAge = 15;
}

比对:Newtonsoft.Json 默认输出Field,并且只读Field也会输出,这点需要注意!

1.9 禁止输出只读属性

上面对只读的Field做了控制,也可以对只读属性做控制,默认情况下会输出只读属性:

var options = new System.Text.Json.JsonSerializerOptions
{
    
    
    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
};
var str = System.Text.Json.JsonSerializer.Serialize(new Model
{
    
    
    Id = 1,
    Name = "小明",
}, options);
Console.WriteLine(str);
//out: {"Id":1,"Name":"小明","IsAdmin":true}


public class Model
{
    
    
    public int Id {
    
     get; set; }
    public string Name {
    
     get; set; }
    public bool IsAdmin => Name == "小明";
}

在某些场景下,减少只读属性的输出会便于存储和数据传递(体积减少),但给前端输出数据慎用,如下:

var options = new System.Text.Json.JsonSerializerOptions
{
    
    
    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
    //忽略只读属性
    IgnoreReadOnlyProperties = true,
};
var str = System.Text.Json.JsonSerializer.Serialize(new Model
{
    
    
    Id = 1,
    Name = "小明",
}, options);
Console.WriteLine(str);
//out: {"Id":1,"Name":"小明"}


public class Model
{
    
    
    public int Id {
    
     get; set; }
    public string Name {
    
     get; set; }
    public bool IsAdmin => Name == "小明";
}

比对:Newtonsoft.Json 默认输出只读属性,没有找到禁止的方法。

1.10 自定义日期格式(DateTime、DateTimeOffset)

默认情况下输出的格式为 ISO 8601-1:2019 参考百度百科 ,默认类似:


var options = new System.Text.Json.JsonSerializerOptions
{
    
    
    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
    WriteIndented = true,
};
var str = System.Text.Json.JsonSerializer.Serialize(new Model
{
    
    
    Id = 1,
    Name = "小明",
    sDateTime = DateTime.Parse("2023-03-04 18:36:12.1234567+08:00"),
    sDateTimeOffset = DateTime.Parse("2023-03-04 18:36:12.1234567+08:00"),
    sTimeSpan = new TimeSpan(1, 2, 3, 4, 5),
}, options);
Console.WriteLine(str);
/*out:
{
  "Id": 1,
  "Name": "小明",
  "sDateTime": "2023-03-04T18:36:12.1234567+08:00",
  "sDateTimeOffset": "2023-03-04T18:36:12.1234567+08:00",
  "sTimeSpan": "1.02:03:04.0050000"
}
*/


public class Model
{
    
    
    public int Id {
    
     get; set; }
    public string Name {
    
     get; set; }
    public DateTime sDateTime {
    
     get; set; }
    public DateTimeOffset sDateTimeOffset {
    
     get; set; }
    public TimeSpan sTimeSpan {
    
     get; set; }
}

如果我们想支持自定义的格式,如下:

var options = new System.Text.Json.JsonSerializerOptions
{
    
    
    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
    WriteIndented = true,
};
options.Converters.Add(new JsonConverterDatetime("yyyy-MM-dd HH:mm:ss.fff zz"));
options.Converters.Add(new JsonConverterDateTimeOffset("yyyy-MM-dd HH:mm:ss.fff zz"));
var str = System.Text.Json.JsonSerializer.Serialize(new Model
{
    
    
    Id = 1,
    Name = "小明",
    sDateTime = DateTime.Parse("2023-03-04 18:36:12.1234567+08:00"),
    sDateTimeOffset = DateTime.Parse("2023-03-04 18:36:12.1234567+08:00"),
    sTimeSpan = new TimeSpan(1, 2, 3, 4, 5),
}, options);
Console.WriteLine(str);
/*out:
{
  "Id": 1,
  "Name": "小明",
  "sDateTime": "2023-03-04 18:36:12.123 +08",
  "sDateTimeOffset": "2023-03-04 18:36:12.123 +08",
  "sTimeSpan": "1.02:03:04.0050000"
}
*/

public class Model
{
    
    
    public int Id {
    
     get; set; }
    public string Name {
    
     get; set; }
    public DateTime sDateTime {
    
     get; set; }
    public DateTimeOffset sDateTimeOffset {
    
     get; set; }
    //public DateOnly sDateOnly { get; set; }
    //public TimeOnly sTimeOnly { get; set; }
    public TimeSpan sTimeSpan {
    
     get; set; }
}

public class JsonConverterDatetime : System.Text.Json.Serialization.JsonConverter<DateTime>
{
    
    
    public string Format {
    
     get; set; }
    public JsonConverterDatetime(string format)
    {
    
    
        if (format == null) throw new ArgumentNullException("format");
        Format = format;
    }
    public override DateTime Read(ref System.Text.Json.Utf8JsonReader reader, Type typeToConvert, System.Text.Json.JsonSerializerOptions options)
    {
    
    
        return DateTime.Parse(reader.GetString());
    }

    public override void Write(System.Text.Json.Utf8JsonWriter writer, DateTime value, System.Text.Json.JsonSerializerOptions options)
    {
    
    
        writer.WriteStringValue(value.ToString(Format));
    }
}

public class JsonConverterDateTimeOffset : System.Text.Json.Serialization.JsonConverter<DateTimeOffset>
{
    
    
    public string Format {
    
     get; set; }
    public JsonConverterDateTimeOffset(string format)
    {
    
    
        if (format == null) throw new ArgumentNullException("format");
        Format = format;
    }
    public override DateTimeOffset Read(ref System.Text.Json.Utf8JsonReader reader, Type typeToConvert, System.Text.Json.JsonSerializerOptions options)
    {
    
    
        return DateTimeOffset.Parse(reader.GetString());
    }

    public override void Write(System.Text.Json.Utf8JsonWriter writer, DateTimeOffset value, System.Text.Json.JsonSerializerOptions options)
    {
    
    
        writer.WriteStringValue(value.ToString(Format));
    }
}

顺便说下:ISO的这种时间格式兼容性还是比较好的,比如:mysql中可以插入 '2023-03-04T18:36:12.1234567+08:00',但不能插入 '2023-03-04 18:36:12.1234567 +08:00',原因是因为后面的 “+08:00” 前不能有空格。

比对:Newtonsoft.Json 默认也是ISO的格式,也支持自定义格式。

1.11 支持输出 DateOnly、TimeOnly

默认.net 6 (.net7可以)不支持 DateOnly、TimeOnly,报错如下:

  • Unhandled exception. System.NotSupportedException: Serialization and deserialization of ‘System.DateOnly’ instances are not supported
  • Unhandled exception. System.NotSupportedException: Serialization and deserialization of ‘System.TimeOnly’ instances are not supported

可以自定义转换器支持,如下:

var options = new System.Text.Json.JsonSerializerOptions
{
    
    
    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
    WriteIndented = true,
};
options.Converters.Add(new JsonConverterDateOnly("yyyy-MM-dd"));
options.Converters.Add(new JsonConverterTimeOnly("HH:mm:ss.fffffff"));
var str = System.Text.Json.JsonSerializer.Serialize(new Model
{
    
    
    Id = 1,
    Name = "小明",
    sDateOnly = DateOnly.Parse("2023-03-04"),
    sTimeOnly = TimeOnly.Parse("18:36:12.1234567"),
}, options);
Console.WriteLine(str);
/*out:
{
  "Id": 1,
  "Name": "小明",
  "sDateOnly": "2023-03-04",
  "sTimeOnly": "18:36:12.1234567"
}
*/


public class Model
{
    
    
    public int Id {
    
     get; set; }
    public string Name {
    
     get; set; }
    public DateOnly sDateOnly {
    
     get; set; }
    public TimeOnly sTimeOnly {
    
     get; set; }
}

public class JsonConverterDateOnly : System.Text.Json.Serialization.JsonConverter<DateOnly>
{
    
    
    public string Format {
    
     get; set; }
    public JsonConverterDateOnly(string format)
    {
    
    
        if (format == null) throw new ArgumentNullException("format");
        Format = format;
    }
    public override DateOnly Read(ref System.Text.Json.Utf8JsonReader reader, Type typeToConvert, System.Text.Json.JsonSerializerOptions options)
    {
    
    
        return DateOnly.Parse(reader.GetString());
    }

    public override void Write(System.Text.Json.Utf8JsonWriter writer, DateOnly value, System.Text.Json.JsonSerializerOptions options)
    {
    
    
        writer.WriteStringValue(value.ToString(Format));
    }
}

public class JsonConverterTimeOnly : System.Text.Json.Serialization.JsonConverter<TimeOnly>
{
    
    
    public string Format {
    
     get; set; }
    public JsonConverterTimeOnly(string format)
    {
    
    
        if (format == null) throw new ArgumentNullException("format");
        Format = format;
    }
    public override TimeOnly Read(ref System.Text.Json.Utf8JsonReader reader, Type typeToConvert, System.Text.Json.JsonSerializerOptions options)
    {
    
    
        return TimeOnly.Parse(reader.GetString());
    }

    public override void Write(System.Text.Json.Utf8JsonWriter writer, TimeOnly value, System.Text.Json.JsonSerializerOptions options)
    {
    
    
        writer.WriteStringValue(value.ToString(Format));
    }
}

比对:新版本的Newtonsoft.Json 支持DateOnly 和 TimeOnly

1.12 将数字输出为字符串

有的时候,我们需要将数字输出为字符串,如下:

var options = new System.Text.Json.JsonSerializerOptions
{
    
    
    //输出是 number => string, 读取时允许 string => number
    NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString | System.Text.Json.Serialization.JsonNumberHandling.WriteAsString,
};

var json = System.Text.Json.JsonSerializer.Serialize(new Model
{
    
    
    Id = 1,
    Score = 99.5f
}, options);
Console.WriteLine(json);
//out: {"Id":"1","Score":"99.5"}
public class Model
{
    
    
    public int Id {
    
     get; set; }
    public float Score {
    
     get; set; }
}

比对:Newtonsoft.Json 可以通过转换器将数字转为字符串。

1.13 忽略默认值的属性

默认情况下:属性有默认值也会被输出,我们可以控制当属性/字段有默认值的时候不再输出(传递给前端时慎用):

var options = new System.Text.Json.JsonSerializerOptions
{
    
    
    DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingDefault,
    IncludeFields = true,
    IgnoreReadOnlyFields = false,
    IgnoreReadOnlyProperties = false,
};

var json = System.Text.Json.JsonSerializer.Serialize(new Model(), options);
Console.WriteLine(json);
//out: {"Id1":1,"IdR1":1,"IdF1":1,"IdFR1":1}
public class Model
{
    
    
    public int Id0 {
    
     get; set; } = 0;
    public int Id1 {
    
     get; set; } = 1;
    public int IdR0 => Id0;
    public int IdR1 => Id1;

    public int IdF0 = 0;
    public int IdF1 = 1;
    public readonly int IdFR0 = 0;
    public readonly int IdFR1 = 1;
}

比对:Newtonsoft.Json 默认也会输出默认值的属性,也可以设置禁止输出。

1.14 在类定义时声明忽略某些属性

[System.Text.Json.Serialization.JsonIgnore]
public int Age {
    
     get; set; }

1.15 在类定义时声明控制属性输出的顺序

[System.Text.Json.Serialization.JsonPropertyOrder(Order = 0)]
public int Age {
    
     get; set; }

1.16 在类定义时声明控制属性输出的名称

[System.Text.Json.Serialization.JsonPropertyName("catAge")]
public int Age {
    
     get; set; }

二、读取时控制(反序列化为模型)

2.1 允许json中多余的逗号

默认情况下,不允许json中存在多余的逗号,如:

{
    
    
  "Id": 1,
  "Name": "小明",
}

这本身并没有错,因为标准json格式是严格的,不允许这个。。。
如果我们读取上面字符串,就会报错如下:

Unhandled exception. System.Text.Json.JsonException: The JSON object contains a trailing comma at the end which is not supported in this mode. Change the reader options. Path: $ | LineNumber: 4 | BytePositionInLine: 0.
—> System.Text.Json.JsonReaderException: The JSON object contains …

为了能顺利读取到,我们可以使用如下方式:

var options = new System.Text.Json.JsonSerializerOptions
{
    
    
    AllowTrailingCommas = true,
};
var json = @"
{
  ""Id"": 1,
  ""Name"": ""小明"",
}
";
var model = System.Text.Json.JsonSerializer.Deserialize<Model>(json, options);

Console.WriteLine($"model.Id={
      
      model.Id},model.Id={
      
      model.Name}");
//out: model.Id=1,model.Id=小明

public class Model
{
    
    
    public int Id {
    
     get; set; }
    public string Name {
    
     get; set; }
}

2.2 允许json中存在注释

默认情况下,不允许json中存在注释,如:

//注释
/*
注释
*/
{
    
    
  //注释
  "Id": 1,
  "Name": "小明",
}

这本身并没有错,因为标准json格式是严格的,不允许这个。。。
如果我们读取上面字符串,就会报错如下:

Unhandled exception. System.Text.Json.JsonException: ‘/’ is an invalid start of a value. Path: $ | LineNumber: 1 | BytePositionInLine: 0.
—> System.Text.Json.JsonReaderException: ‘/’ is an invalid start of a value. …

为了能顺利读取到,我们可以使用如下方式:

var options = new System.Text.Json.JsonSerializerOptions
{
    
    
    //因为我们是直接反序列化为模型,所以这里 跳过注释
    ReadCommentHandling = System.Text.Json.JsonCommentHandling.Skip,
};
var json = @"
//注释
/*
注释
*/
{
  //注释
  ""Id"": 1,
  ""Name"": ""小明""
}
";
var model = System.Text.Json.JsonSerializer.Deserialize<Model>(json, options);

Console.WriteLine($"model.Id={
      
      model.Id},model.Name={
      
      model.Name}");
//out: model.Id=1,model.Name=小明

2.3 允许将json中的 “123” => 123,“NaN” => float.NaN

默认情况下,json中的字符串不能转为数字,如下,会报错:

var json = @"
{
  ""Id"": ""123"",
}
";
var model = System.Text.Json.JsonSerializer.Deserialize<Model>(json);
/*exception:
Unhandled exception. System.Text.Json.JsonException: The JSON value could not be converted to System.Int32. Path: $.Id | LineNumber: 2 | BytePositionInLine: 13.
*/

public class Model
{
    
    
    public int Id {
    
     get; set; }
}

如果我们想实现自动转换,如下:

var options = new System.Text.Json.JsonSerializerOptions
{
    
    
    //允许将 "123" 转为数字 123
    NumberHandling = System.Text.Json.Serialization.JsonNumberHandling.AllowReadingFromString,
};
var json = @"
{
  ""Id"": ""123"",
  ""Score"":""NaN""
}
";
var model = System.Text.Json.JsonSerializer.Deserialize<Model>(json, options);

Console.WriteLine($"model.Id={
      
      model.Id},model.Score={
      
      model.Score}");
//model.Id=123,model.Score=NaN

public class Model
{
    
    
    public int Id {
    
     get; set; }
    public float Score {
    
     get; set; }
}

顺便说一下:float中的NaN,Infinity,-Infinity 都是有意义的。

2.4 允许忽略属性名大小写

默认大小写敏感,如下:
在这里插入图片描述
如果想忽略大小写属性,如下:
new JsonSerializerOptions { PropertyNameCaseInsensitive = true }
在这里插入图片描述

注意:Newtonsoft.Json 默认忽略大小写。

猜你喜欢

转载自blog.csdn.net/u010476739/article/details/129337119