分享

关于使用System.Text.Json解析这些坑

 Csharp小记 2024-04-03 发布于江苏

前言

    在高版本的.Net中,微软集成了System.Text.Json用来实现对Json的序列化和反序列化,这样我们就不要再额外引入其他Json类库(Newtonsoft.Json等)来做解析了,不过在使用过程中,还是发现了一些坑,每当遇到都会觉得还是Newtonsoft.Json香,不过吐槽归吐槽,像我这样有强迫症的,能用原生尽量不会选择第三方,除非遇到没办法解决或者解决起来超级复杂的问题。

但综合而言,遇到的坑基本都是格式问题。。。







开发环境:.NET 6

开发工具:Visual Studio 2022

 









实现步骤

  1. 首先我们看看序列化的效果
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"}

  1. 以上着重看下时间格式,会发现他跟我们平常使用的不一样,这也就是他自动序列化成了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.
  1. 虽然可以通过转换时间格式来解决这个问题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")); } }

  1. 最后调用的时候进行转换
JsonSerializerOptions options = new JsonSerializerOptions(); options.Converters.Add(new DateTimeJsonFormat()); model newModel = JsonSerializer.Deserialize<model>(newJson, options);


  1. 同理,当涉及到其他类型的时候亦可以这样处理,如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);    }}
  1. 然后调用的时候再加一个类型
     JsonSerializerOptions options = new JsonSerializerOptions(); options.Converters.Add(new DateTimeJsonFormat()); options.Converters.Add(new IntJsonFormat()); model newModel = JsonSerializer.Deserialize<model>(newJson, options);
 
  1. 以上是直接使用的时候需要进行的操作,也就是可以封装一个方法进行调用,但是在WebApi中的话,则可以直接在Program中进行配置实现
    builder.Services.AddControllers().AddJsonOptions(options =>{ options.JsonSerializerOptions.Converters.Add(new DateTimeJsonFormat()); options.JsonSerializerOptions.Converters.Add(new IntJsonFormat());});

实现效果

 

☛☛☛点击此处下载源码☚☚☚



    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多