.NET Core 3.0 JsonSerializer.Deserialize 返回dynamic类型对象
阅读原文时间:2023年07月09日阅读:2

.NET Core 3.0 JsonSerializer.Deserialize to dynamic object

因为官方还不支持返回动态类型的对象,只能自己手写一个,临时测试了下没问题,还有些地方不完善的可以自己拿去修改下。

.net Core3 no support

add using:

  • using System.Text.Json;

  • using System.Text.Json.Serialization;

    /// <summary>
    /// Temp Dynamic Converter
    /// by:tchivs@live.cn
    /// </summary>
    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&lt;string, object&gt; 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&amp;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&lt;object?&gt; list = new List&lt;object?&gt;();
        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() }
    };
    return JsonSerializer.Deserialize("{OK:"200"}", serializerOptions);