zoukankan      html  css  js  c++  java
  • JsonSerializer反序列化

    string strjson = "{ "Id":1,"Name":"u5F20u73CA","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":"u5F20u73CA","BirthDay":"2020-07-27T00:00:00+08:00"}";  
                    var jsun = SerializerExtend.Fun(typeof(Student), strjson);

    这个方法,本人只是做了简单的认证,可能还有一些要完善的地方,如有发现,请留言。

    此方法和第2种方法一样。就是当json字符串无效时会直接报错。

  • 相关阅读:
    linux脚本练习之将数据导入oracle表
    linux脚本之一个程序调用另一个程序
    使用客户端Navicat连接数据库oracle19c
    centos7安装与卸载oracle19c
    Redis-cluster集群搭建(redis版本5.0.4)
    linux下redis的哨兵模式
    使用POI导入Excel文件
    MySQL8.0搭建MGR集群(MySQL-shell、MySQL-router)
    MySQL Shell用法
    CentOS 7下使用rpm包安装MySQL8.0
  • 原文地址:https://www.cnblogs.com/xiaoZhang521/p/13387985.html
Copyright © 2011-2022 走看看