在高版本的.Net中,微软集成了System.Text.Json用来实现对Json的序列化和反序列化,这样我们就不要再额外引入其他Json类库(Newtonsoft.Json等)来做解析了,不过在使用过程中,还是发现了一些坑,每当遇到都会觉得还是Newtonsoft.Json 香,不过吐槽归吐槽,像我这样有强迫症的,能用原生尽量不会选择第三方,除非遇到没办法解决或者解决起来超级复杂的问题。 但综合而言,遇到的坑基本都是格式问题。。。 开发环境:.NET 6 开发工具:Visual Studio 2022
class model { public int id { get; set; } public string name { get; set; } public DateTime dateTime { get; set; } }
model model = new model { id = 1, name = "张三", dateTime = DateTime.Now }; string json=JsonSerializer.Serialize(model); Console.WriteLine(json); //输出{"id":1,"name":"\u5F20\u4E09","dateTime":"2024-04-01T15:04:08.9608596+08:00"}
- 以上着重看下时间格式,会发现他跟我们平常使用的不一样,这也就是他自动序列化成了ISO8601格式,当我们拿这段json直接反序列化的时候,是没有问题的,但是换成正常时间格式的话,就会抛出异常,如下:
string newJson = "{\"id\":1,\"name\":\"张三\",\"dateTime\":\"" + DateTime.Now + "\"}"; model newModel = JsonSerializer.Deserialize<model>(newJson); //抛出异常 The JSON value could not be converted to System.DateTime.
- 虽然可以通过转换时间格式来解决这个问题
DateTime.Now.ToString("yyyy-MM-ddTHH:mm:sszzz") ,但是在涉及到交互的时候会诸多不便,所以我们需要自定义一个转换格式化的类
public class DateTimeJsonFormat : JsonConverter<DateTime> {
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.String || reader.TokenType == JsonTokenType.Null) { if (DateTime.TryParse(reader.GetString(), out DateTime date)) { return date; } else { return DateTime.MinValue; }
} return reader.GetDateTime(); } public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) { writer.WriteStringValue(value.ToString("yyyy-MM-dd HH:mm:ss")); } }
JsonSerializerOptions options = new JsonSerializerOptions(); options.Converters.Add(new DateTimeJsonFormat()); model newModel = JsonSerializer.Deserialize<model>(newJson, options);
- 同理,当涉及到其他类型的时候亦可以这样处理,如Null或Int处理,下面是Int处理,对与此处理在强类型语言下一般没问题,但是涉及到一些弱类型可能会出现。比如js提交表单的时候,如果没有进行类型转换,则一样会报错。或者说直接将上面Json中的Id的值改为空或者字符串格式。
public class IntJsonFormat : JsonConverter<int>{ public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options){ if (reader.TokenType == JsonTokenType.String) { if (int.TryParse(reader.GetString(), out int result)) { return result; } else { return 0; } } return reader.GetInt32(); } public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options){ writer.WriteNumberValue(value); }}
JsonSerializerOptions options = new JsonSerializerOptions(); options.Converters.Add(new DateTimeJsonFormat()); options.Converters.Add(new IntJsonFormat()); model newModel = JsonSerializer.Deserialize<model>(newJson, options);
- 以上是直接使用的时候需要进行的操作,也就是可以封装一个方法进行调用,但是在WebApi中的话,则可以直接在
Program 中进行配置实现builder.Services.AddControllers().AddJsonOptions(options => { options.JsonSerializerOptions.Converters.Add(new DateTimeJsonFormat()); options.JsonSerializerOptions.Converters.Add(new IntJsonFormat()); });
|