C#_Json序列化(System.Text.Json)

一、前言

System.Text.Json 命名空间提供用于序列化和反序列化 JavaScript 对象表示法 (JSON) 的功能。

  • 该库是作为 .NET Core 3.0 及更高版本共享框架的一部分内置的。

  • 对于早期版本的框架,请安装 System.Text.Json NuGet 包。 包支持以下框架:

    • .NET Standard 2.0 及更高版本
    • .NET Framework 4.7.2 及更高版本
    • .NET Core 2.0、2.1 和 2.2

    序列化行为:

    • 默认情况下,所有公共属性都会序列化。 可以指定要忽略的属性。
    • 默认情况下,JSON 会缩小(就是没有换行等格式)。 可以对 JSON 进行优质打印。
    • 默认情况下,JSON 名称的大小写与 .NET 名称匹配。 可以自定义 JSON 名称大小写。
    • 默认情况下忽略字段。 可以包含字段。

二、最简单的Json序列化和反序列化

public class Foo
{
    public byte Member1 { get; set; }

    public UInt16 Member2 { get; set; }

    public UInt32 Member3 { get; set; }

    public bool Member4 { get; set; }

    public UInt32[] Member5 { get; set; }
}
        static void Main(string[] args)
        {
            Foo foo = new Foo
            {
                Member1 = 0x11,
                Member2 = 0x22,
                Member3 = 0x33,
                Member4 = true,
                Member5 = new UInt32[] { 0x44, 0x55, 0x66 },
            };
            string json = System.Text.Json.JsonSerializer.Serialize(foo);

            Console.WriteLine(json);//{"Member1":17,"Member2":34,"Member3":51,"Member4":true,"Member5":[68,85,102]}
            File.WriteAllText(@"test.json", json);

            Foo f = JsonSerializer.Deserialize<Foo>(json);
        }

三、控制序列化行为

那就需要使用到JsonSerializerOptions类型的对象。

Type Property 说明
bool AllowTrailingCommas 反序列化时是否允许末尾有多余的逗号,默认为法false,所以如果json字符串默认有多余的逗号还需要反序列化们就可以将此属性设置为true。
bool WriteIndented 该值定义Json是否应使用整齐打印。默认情况下为法false。
bool PropertyNameCaseInsensitive 反序列化的时候不区分大小写,默认为false。
JsonNamingPolicy PropertyNamingPolicy 设置为 JsonNamingPolicy.CamelCase的时候,所有JSON属性名称使用camel大小写。
bool IgnoreReadOnlyProperties 忽略只读属性,默认值为false
bool IgnoreNullValues 忽略值为Null的属性,默认值为false
JsonCommentHandling ReadCommentHandling 反序列化时候怎么处理注释。默认为Disallow,允许注释的时候可以设置为Skip。

值得一提的是,用的什么JsonSerializerOptions序列化的就需要使用对应的JsonSerializerOptions反序列化,不需要另外转换啥的

1、自定义属性的名称和值

public class Foo
{
    public byte Member1 { get; set; }

    [JsonPropertyName("M2")]
    public UInt16 Member2 { get; set; }

    public UInt32 Member3 { get; set; }

    public bool Member4 { get; set; }

    public UInt32[] Member5 { get; set; }
}

在属性上定义JsonPropertyName特性,此特性设置的属性名称:

  • 同时适用于两个方向(序列化和反序列化)。
  • 优先于属性命名策略。
static void Main(string[] args)
{
    Foo foo = new Foo
    {
        Member1 = 0x11,
        Member2 = 0x22,
        Member3 = 0x33,
        Member4 = true,
        Member5 = new UInt32[] { 0x44, 0x55, 0x66 },
    };
    JsonSerializerOptions options = new JsonSerializerOptions
    {
        WriteIndented = true,
    };

    string json = System.Text.Json.JsonSerializer.Serialize<Foo>(foo, options);

    Console.WriteLine(json);
    File.WriteAllText(@"test.json", json);

    string j = File.ReadAllText(@"test.json");
    Foo f = JsonSerializer.Deserialize<Foo>(j,options);
}
output:
{
  "Member1": 17,
  "M2": 34,
  "Member3": 51,
  "Member4": true,
  "Member5": [
    68,
    85,
    102
  ]
}

2、对所有 JSON 属性名称使用 camel 大小写

将上述代码的JsonSerializerOptions对象修改为:

        JsonSerializerOptions options = new JsonSerializerOptions
        {
            WriteIndented = true,
            PropertyNamingPolicy=JsonNamingPolicy.CamelCase,
        };
output:
{
  "member1": 17,
  "M2": 34,
  "member3": 51,
  "member4": true,
  "member5": [
    68,
    85,
    102
  ]
}

因为JsonPropertyName特性的优先级高于属性命名策略,所以还是“M2”。

3、使用自定义 JSON 属性命名策略

还是设置PropertyNamingPolicy的值,不过这个值不在使用预定义好的CamelCase,需要我们自己定义一个。

public class UpperCaseNamingPolicy : JsonNamingPolicy
{
    public override string ConvertName(string name) =>
        name.ToUpper();
}
        JsonSerializerOptions options = new JsonSerializerOptions
        {
            WriteIndented = true,
            PropertyNamingPolicy = new UpperCaseNamingPolicy(),
        };
output:
{
  "MEMBER1": 17,
  "M2": 34,
  "MEMBER3": 51,
  "MEMBER4": true,
  "MEMBER5": [
    68,
    85,
    102
  ]
}

4、自定义属性的值

比如需要将枚举类型的整形值序列化为字符串名称,则可以使用系统预定义好的JsonStringEnumConverter。

添加一个枚举类型:

public enum TestEnum
{
    EnumA=0,
    EnumB,
    EnumC
}

public class Foo
{
    public byte Member1 { get; set; }

    [JsonPropertyName("M2")]
    public UInt16 Member2 { get; set; }

    public UInt32 Member3 { get; set; }

    public bool Member4 { get; set; }

    public UInt32[] Member5 { get; set; }

    public TestEnum Member6 { get; set; }
}
        JsonSerializerOptions options = new JsonSerializerOptions
        {
            WriteIndented = true,
            Converters = { new JsonStringEnumConverter()},
        };
output:
{
  "Member1": 17,
  "M2": 34,
  "Member3": 51,
  "Member4": true,
  "Member5": [
    68,
    85,
    102
  ],
  "Member6": "EnumB"
}

也可以自定义Converter,需要继承JsonConverter类,官方链接。举例将上例中的值保存为16进制格式。

public class JsonDecimalHexConverter : JsonConverter<byte>
{
    public override byte Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
       string val= reader.GetString();

       return System.Convert.ToByte(val, 16);
    }

    public override void Write(Utf8JsonWriter writer, byte value, JsonSerializerOptions options)
    {
        writer.WriteStringValue("0x" + value.ToString("x"));
    }
}
        JsonSerializerOptions options = new JsonSerializerOptions
        {
            WriteIndented = true,
            Converters = { new JsonDecimalHexConverter()},
        };
output:
{
  "Member1": "0x11",
  "M2": 34,
  "Member3": 51,
  "Member4": true,
  "Member5": [
    68,
    85,
    102
  ],
  "Member6": 1
}

上述写法还可以这样使用特性标记。

    [JsonConverter(typeof(JsonDecimalHexConverter))]
    public byte Member1 { get; set; }

5、忽略属性

  • 若要忽略单个属性,使用 [JsonIgnore] 特性。对应的有[JsonInclude]特性(.Net Core 3.1不支持)。
  • 若要忽略只读属性,可将属性IgnoreReadOnlyProperties设置为true。
  • 若要忽略值为Null的属性,可将属性IgnoreNullValues设置为true。

6、允许无效的Json

  • 允许注释。将ReadCommentHandling属性设置JsonCommentHandling.Skip。
  • 允许尾随逗号。将AllowTrailingCommas属性设置为true。

你可能感兴趣的:(BinarySerialize,json)