获取 'System.Text.Json.JsonElement' 不包含 'result' 解析为 JsonSerializer.DeserializeAsync

getting 'System.Text.Json.JsonElement' does not contain 'result' Parsing with JsonSerializer.DeserializeAsync

我JSON的回复结构如下

{
   "statusCode": 200,
   "result": {
      "generalInfo": {
         "firstName": "",
         "lastName": ""
      },
      "isError": false      
   },
   "sentDate": "2022-02-06T10:04:06.6853775Z",
}

var response = await _httpClient.PostAsJsonAsync(address, model);
Stream responseBody = await response.Content.ReadAsStreamAsync();

            

端点的响应实际上有点复杂,我只想提取特定字段,所以我使用了动态

dynamic data = await JsonSerializer.DeserializeAsync<dynamic>(responseBody)

var dataString = data.ToString();

// dataString 是

{"result":{"generalInfo":{"firstName":"John","lastName":"Doe"},"isError":false}

如果我尝试像这样访问动态属性

var firstName = data.result.generalInfo.firstName;
var lastName = data.result.generalInfo.lastName;
var isErr = data.IsError;

我遇到异常

'System.Text.Json.JsonElement' does not contain a definition for 'result'

问题不在于DeserializeAsync,而是System.Text.Json使用了JsonElements,所以动态值实际上是一个JsonElement。您需要解析来自 JsonElement.

的数据

但是,如果您使用的是 .Net 6,则可以使用 JsonNode:

// deserialize into JsonNode
JsonNode data = await JsonSerializer.DeserializeAsync<JsonNode>(responseBody);
// OR parse the json string
JsonNode data = JsonNode.Parse(dataString);

int statusCode = (int)data["statusCode"];
var firstName = (string)data["result"]["generalInfo"]["firstName"];
var lastName = (string)data["result"]["generalInfo"]["lastName"];
var isErr = (bool)data["result"]["isError"];

Demo in .Net6

dynamic 的支持已添加到 .Net 6 预览版 v4-6 中,但在最终发布之前已被删除,以支持上述 JsonNode 方法。有关详细信息,请参阅 github What's new in .NET 6 Preview 7


否则,您可以手动解析它:

bool isError = false;
string firstName = ""; 
string lastName = "";
if (data is JsonElement elt && elt.TryGetProperty("result", out elt))
{
    isError = elt.TryGetProperty("isError", out JsonElement boolElt) ? boolElt.GetBoolean() : false;
    if (elt.TryGetProperty("generalInfo", out var genInfo))
    {
        firstName = genInfo.TryGetProperty("firstName", out var firstElt) ? firstElt.GetString() : "";
        lastName = genInfo.TryGetProperty("lastName", out var lastElt) ? lastElt.GetString() : "";
    }
}

但是,如果可以的话,我的首选方法总是反序列化为已定义的 类,因为这会让生活变得更轻松:

public class GeneralInfo
{
    public string firstName { get; set; }
    public string lastName { get; set; }
}

public class Result
{
    public GeneralInfo generalInfo { get; set; }
    public bool isError { get; set; }
}

public class Root
{
    public Result result { get; set; }
}

var data = await JsonSerializer.DeserializeAsync<Root>(responseBody);
var firstName = data.result.generalInfo.firstName;