JsonSerializer反序列化
string strjson = "{ \"Id\":1,\"Name\":\"\u5F20\u73CA\",\"BirthDay\":\"2020-07-27T00:00:00+08:00\"}"; JsonSerializer.Deserialize<Student>(strjson);
当我们用静态类 JsonSerializer 反序列化一个字符串strjson 时,如果strjson 不是一个有效的Json 字符串,就会报错,
所以我们封装一个方法,来处理JsonException发生的情况
1:第一种方法最简单
public static class JsonSerializerExtensions { public static TValue Deserialize<TValue>(string json, JsonSerializerOptions options = null) where TValue : new() { try { return JsonSerializer.Deserialize<TValue>(json, options); } catch (JsonException) { return new TValue(); } } }
直接用try/catch包起来。
2:只有json字符串是有效的,我们就可以转化成一个动态对象dynamic,直接上代码
public class DynamicJsonConverter : JsonConverter<dynamic> { public override dynamic Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.True) { return true; } if (reader.TokenType == JsonTokenType.False) { return false; } if (reader.TokenType == JsonTokenType.Number) { if (reader.TryGetInt64(out long l)) { return l; } return reader.GetDouble(); } if (reader.TokenType == JsonTokenType.String) { if (reader.TryGetDateTime(out DateTime datetime)) { return datetime; } return reader.GetString(); } if (reader.TokenType == JsonTokenType.StartObject) { using JsonDocument documentV = JsonDocument.ParseValue(ref reader); return ReadObject(documentV.RootElement); } // Use JsonElement as fallback. // Newtonsoft uses JArray or JObject. JsonDocument document = JsonDocument.ParseValue(ref reader); return document.RootElement.Clone(); } private object ReadObject(JsonElement jsonElement) { IDictionary<string, object> expandoObject = new ExpandoObject(); foreach (var obj in jsonElement.EnumerateObject()) { var k = obj.Name; var value = ReadValue(obj.Value); expandoObject[k] = value; } return expandoObject; } private object? ReadValue(JsonElement jsonElement) { object? result = null; switch (jsonElement.ValueKind) { case JsonValueKind.Object: result = ReadObject(jsonElement); break; case JsonValueKind.Array: result = ReadList(jsonElement); break; case JsonValueKind.String: //TODO: Missing Datetime&Bytes Convert result = jsonElement.GetString(); break; case JsonValueKind.Number: //TODO: more num type result = 0; if (jsonElement.TryGetInt64(out long l)) { result = l; } break; case JsonValueKind.True: result = true; break; case JsonValueKind.False: result = false; break; case JsonValueKind.Undefined: case JsonValueKind.Null: result = null; break; default: throw new ArgumentOutOfRangeException(); } return result; } private object? ReadList(JsonElement jsonElement) { IList<object?> list = new List<object?>(); foreach (var item in jsonElement.EnumerateArray()) { list.Add(ReadValue(item)); } return list.Count == 0 ? null : list; } public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options) { // writer.WriteStringValue(value.ToString()); } }
这只是帮助类,要怎么用呐?
var serializerOptions = new JsonSerializerOptions { Converters = { new DynamicJsonConverter() } }; var str = "{\"OK\":\"200\"}"; var res = JsonSerializer.Deserialize<dynamic>(str, serializerOptions);
这种情况有一个小bug,就是当json字符串无效时会直接报错。
3:写一个校验方法,判断json字符串和给定的类型是否匹配
public class SerializerExtend { public static bool Fun(Type type, string jsonStr) { JObject jObject; try { jObject = JObject.Parse(jsonStr); } catch (JsonReaderException) { return false; } var propertys = type.GetProperties(); foreach (JProperty child in jObject.Children()) { var oneBool = false; foreach (var property in propertys) { //先判断名称是否一样 if (string.Equals(property.Name, child.Name, StringComparison.OrdinalIgnoreCase)) { //再判断类型是否一样 if (child.HasValues) { if (child.Type == JTokenType.Object) { var childBool = Fun(property.PropertyType, child.Value.ToString()); if (childBool == false) return false; } else { if (dic[Type.GetTypeCode(property.PropertyType)] == child.Value.Type) { oneBool = true; break; } } } } } if (oneBool == false) //没有匹配上 return false; } return true; } private static Dictionary<TypeCode, JTokenType> dic { get { if (_dic == null) DicInit(); return _dic; } } private static Dictionary<TypeCode, JTokenType> _dic = null; private static void DicInit() { _dic = new Dictionary<TypeCode, JTokenType>(); dic.Add(TypeCode.Empty, JTokenType.String); dic.Add(TypeCode.Object, JTokenType.Object); dic.Add(TypeCode.DBNull, JTokenType.Null); dic.Add(TypeCode.Boolean, JTokenType.Boolean); dic.Add(TypeCode.Char, JTokenType.String); dic.Add(TypeCode.SByte, JTokenType.Integer); dic.Add(TypeCode.Byte, JTokenType.Integer); dic.Add(TypeCode.Int16, JTokenType.Integer); dic.Add(TypeCode.UInt16, JTokenType.Integer); dic.Add(TypeCode.Int32, JTokenType.Integer); dic.Add(TypeCode.UInt32, JTokenType.Integer); dic.Add(TypeCode.Int64, JTokenType.Integer); dic.Add(TypeCode.UInt64, JTokenType.Integer); dic.Add(TypeCode.Single, JTokenType.Float); dic.Add(TypeCode.Double, JTokenType.Float); dic.Add(TypeCode.Decimal, JTokenType.Float); dic.Add(TypeCode.DateTime, JTokenType.Date); dic.Add(TypeCode.String, JTokenType.String); } }
使用方法
string strjson = "{ \"Id\":1,\"Name\":\"\u5F20\u73CA\",\"BirthDay\":\"2020-07-27T00:00:00+08:00\"}"; var jsun = SerializerExtend.Fun(typeof(Student), strjson);
这个方法,本人只是做了简单的认证,可能还有一些要完善的地方,如有发现,请留言。
此方法和第2种方法一样。就是当json字符串无效时会直接报错。
posted on 2020-07-27 22:06 IT_xiaozhang 阅读(3337) 评论(0) 编辑 收藏 举报