【问题标题】:How to Deserialise JsonDocument To POCO Using System.Text.Json如何使用 System.Text.Json 将 JsonDocument 反序列化为 POCO
【发布时间】:2021-01-30 18:13:27
【问题描述】:
使用 HttpClient 我将一个 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",......}
如果类型未知,如何将其反序列化?
【问题讨论】:
标签:
c#
json
system.text.json
【解决方案1】:
我想像这样从 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;
}
}
}
【解决方案2】:
我可能是错的,但如果你使用一个你坚持的参数
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来反序列化了。看起来效果不错。