如何使用 System.Text.Json 将 JsonDocument 反序列化为 POCO

How to Deserialise JsonDocument To POCO Using System.Text.Json

使用 HttpClient 我 post 一个 json 文档到我的控制器。

   public async Task<string> PostAsync<T>(string url, T doc)
   {
        var json = JsonConvert.SerializeObject(doc);
        var response = await mHttp.PostAsync(url, new StringContent(json));
   }

当我在这里检查控制器时:

public async Task<ActionResult> Post([FromBody] object doc,string fid)

对象文档具有以下格式:

ValueKind = Object : "{"id": "101zsdfgfgh","fid": "test1",......}

如果类型未知,如何反序列化?

我可能是错的,但如果你使用一个参数,你就会坚持

 System.Text.Json 

所以我认为答案是不使用参数

public async Task<ActionResult> Post([FromBody] object doc,string fid)

改为

public async Task<ActionResult> Post(string fid)

然后像这样反序列化请求的内容。

   string obj = await new StreamReader(HttpContext.Request.Body).ReadToEndAsync();
   var doc = JsonConvert.DeserializeObject<dynamic>(obj);

然后你可以使用 JsonConvert 到 deserialize.Seems 很好地工作。

我想像这样从 JsonDocument 转换

dynamic obj=jsonDoc.ToObject();

所以我做了一个扩展方法。 这些属性最终是 JsonElements - 这对我来说很好,通常我需要做一个 ToString()。

所以这是我的代码(没有经过彻底测试,请注意...)

using System.Dynamic;
using System.Text.Json;
using System.Collections.Generic;

namespace MyJsonExtensions
{
    public static class Extensions
    {
        public static object ToObject(this JsonDocument jsonDoc)
        {
            return Convert(jsonDoc.RootElement);
        }

        private static object Convert(JsonElement json)
        {

          if (json.ValueKind!=JsonValueKind.Array && json.ValueKind!=JsonValueKind.Object)
          {
            return json;
          }

          var serialized=JsonSerializer.Deserialize<ExpandoObject>(json.GetRawText());
          var output=new ExpandoObject();
          var outputDict=(IDictionary<string,object>)output;
          
          foreach (var prop in (IDictionary<string,object>)serialized)
          {
            var propValue=(JsonElement)prop.Value;

            switch (propValue.ValueKind)
            {
              case JsonValueKind.Array:
                var list=new List<object>();
                foreach (var item in propValue.EnumerateArray())
                {
                  list.Add(Convert(item));
                }
                outputDict[prop.Key]=list.ToArray();
                break;

              case JsonValueKind.Object:
                ExpandoObject val=new ExpandoObject();
                var node=(IDictionary<string,object>)val;
                foreach (var objElement in propValue.EnumerateObject())
                {
                  var v=Convert(objElement.Value);
                  node.Add(objElement.Name,v);
                }
                outputDict[prop.Key]=val;
                break;

              default:
                outputDict[prop.Key]=prop.Value;
                break;
            }            
          }

          return output;
        }

    }
}