首页 > 解决方案 > 我有比这更好的反序列化谷歌之家 JSON 的方法吗?

问题描述

所以我正在尝试反序列化 Google 主页 JSON(使用 Dialogflow),这样我就可以轻松地使用它,即能够像这样调用它:

        string myname = tlr?.queryResult?.parameters?.name ?? "Bill";

具体来说,我正在寻求一种更好的方式来布局 Json 以更好地处理子部分,目前顶层的所有内容都使得深度嵌套的 Json neigh 难以阅读。

在底部,是我想要的工作,但我不确定如何让 C# 管理它。

Json 看起来像这样:

{
  "responseId": "64de67a1-7924-437f-aa29-dad7a1451b58",
  "queryResult": 
  {
    "queryText": "Daves Mud",
    "parameters": 
    {
      "name": "Dave"
    },
    "allRequiredParamsPresent": true,
    "fulfillmentMessages": 
    [
      {
        "text": 
        {
          "text": 
          [
              ""
          ]
        }
      }
    ],
    "intent": 
    {
      "name": "projects/davesmud/agent/intents/4e264eaf-30bc-4db3-8a51-bbfe4b4a3199",
      "displayName": "actions.intent.PLAY_GAME"
    },
    "intentDetectionConfidence": 1,
    "languageCode": "en"
  },
  "originalDetectIntentRequest": {
    "payload": {}
  },
  "session": "projects/davesmud/agent/sessions/a6ef333e-c870-b00e-9b94-ab36d64de757"
}

我处理它的代码是(有效):

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Collections.Generic;

namespace Daves.Mud
{
    public class parameters
    {
        [JsonProperty("name")]
        public string name {get;set;}
    }
    public class queryResult
    {
        [JsonProperty("queryText")]
        public string queryText {get;set;}

        [JsonProperty("parameters")]
        public parameters parameters {get; set;}

        [JsonProperty("allRequiredParamsPresent")]
        public string allRequiredParamsPresent {get;set;}

        [JsonProperty("fulfillmentMessages")]
        public List<fulfillmentMessages> fulfillmentMessages {get;set;}

        [JsonProperty("intent")]
        public intent intent {get; set;}

        [JsonProperty("intentDetectionConfidence")]
        public float intentDetectionConfidence {get; set;}

        [JsonProperty("languageCode")]
        public string languageCode {get; set;}
    }

    public class text
    {
        [JsonProperty("text")]
        public List<string> textarr {get; set;}
    }

    public class fulfillmentMessages
    {
        [JsonProperty("text")]
        public text text {get; set;}
    }
    public class intent
    {
        [JsonProperty("name")]
        public string name {get; set;}

        [JsonProperty("displayName")]
        public string displayName {get; set;}
    }

    public class payload
    {
        // don't know what gets passed to this yet.
    }

    public class originalDetectIntentRequest
    {
        [JsonProperty("payload")]
        public payload payload {get; set;}
    }

    public class  TopLevelRequest
    {
        [JsonProperty("responseID")]
        public string responseID {get;set;}

        [JsonProperty("queryResult")]
        public queryResult queryResult {get; set;}

        [JsonProperty("originalDetectIntentRequest")]
        public originalDetectIntentRequest originalDetectIntentRequest {get; set;}

        [JsonProperty("session")]
        public string session {get; set;}

    }


    public static class HttpTriggerAlexaAdventure
    {
        [FunctionName("HttpTriggerAlexaAdventure")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            string name = req.Query["name"];

            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            TopLevelRequest tlr = JsonConvert.DeserializeObject<TopLevelRequest>(requestBody);

            string myname = tlr?.queryResult?.parameters?.name ?? "Bill";


/*            dynamic data = JsonConvert.DeserializeObject(requestBody);
            name = name ?? data?.name;

            return name != null
                ? (ActionResult)new OkObjectResult($"Hello, {name}")
                : new BadRequestObjectResult("Please pass a name on the query string or in the request body");
*/
            return(ActionResult)new OkObjectResult($"Hello, {myname}");
        }
    }
}

我想要的是这样的东西,注意这不会编译,因为类不能以这种方式与属性一起使用(我认为它们被调用)。

public class  TopLevelRequest
{
   [JsonProperty("responseID")]
    public string responseID {get;set;}

    [JsonProperty("queryResult")]
    public class queryResult 
    {
        [JsonProperty("queryText")]
        public string queryText {get;set;}

        [JsonProperty("parameters")]
        public class parameters 
        {
            [JsonProperty("name")]
            public string name {get;set;}
        }

        [JsonProperty("allRequiredParamsPresent")]
        public string allRequiredParamsPresent {get;set;}

        [JsonProperty("fulfillmentMessages")]
        public class fulfillmentMessages
        {
          [JsonProperty("text")]
          public class text
          {
              [JsonProperty("text")]
              public List<string> textarr {get; set;}
          }



...

如上所述,该类是在另一个类中定义的,因此只定义了一个顶级类,并且 json 更容易遵循,因为您不需要在源代码周围跳转。

任何建议都将不胜感激,因为如果这是最好的 c# 可以为 json 处理的可读性做的事情,我会渴望我以前在 Perl 中是如何做到的...... :-)

编辑 - 我玩了更多,并找到了一种至少保持层次结构的方法,这主要是我所追求的。说它漂亮虽然是一个光头谎言,但我相信它需要改进。

public class  TopLevelRequest
{
    [JsonProperty("responseID")] public string responseID {get;set;}

    [JsonProperty("queryResult")] public queryResult_class queryResult {get; set;}  public class queryResult_class
    {
        [JsonProperty("queryText")] public string queryText {get;set;}

        [JsonProperty("parameters")] public parameters_cl parameters {get; set;}  public class parameters_cl
        {
            [JsonProperty("name")] public string name {get;set;}
        }

        [JsonProperty("allRequiredParamsPresent")] public string allRequiredParamsPresent {get;set;}

        [JsonProperty("fulfillmentMessages")] public List<fulfillmentMessages_class> fulfillmentMessages {get;set;}  public class fulfillmentMessages_class
        {
            [JsonProperty("text")] public text_class text {get; set;}  public class text_class
            {
                [JsonProperty("text")] public List<string> textarr {get; set;}
            }
        }

        [JsonProperty("intent")] public intent_class intent {get; set;}  public class intent_class
        {
            [JsonProperty("name")] public string name {get; set;}
            [JsonProperty("displayName")] public string displayName {get; set;}
        }

        [JsonProperty("intentDetectionConfidence")] public float intentDetectionConfidence {get; set;}
        [JsonProperty("languageCode")] public string languageCode {get; set;}
    }

    [JsonProperty("originalDetectIntentRequest")] public originalDetectIntentRequest_class originalDetectIntentRequest {get; set;}  public class originalDetectIntentRequest_class
    {
        [JsonProperty("payload")] public payload_class payload {get; set;} public class payload_class
        {
            // don't know what gets passed to this yet.
        }
    }

    [JsonProperty("session")] public string session {get; set;}
}

如果有更好的方法请告诉我:-)!

编辑 2 - 我尝试按照一张海报的建议复制 json,然后使用、编辑、特殊粘贴、将 json 作为类粘贴到 Visual Studio 中。

它直接开箱即用,这就是它产生的结果,我确信我可以像上面那样重新排序它,我很惊讶我不需要任何 JsonProperties 本身就可以大大简化代码。

这是它产生的代码:

public class TopLevelRequest
{
    public string responseId { get; set; }
    public Queryresult queryResult { get; set; }
    public Originaldetectintentrequest originalDetectIntentRequest { get; set; }
    public string session { get; set; }
}

public class Queryresult
{
    public string queryText { get; set; }
    public Parameters parameters { get; set; }
    public bool allRequiredParamsPresent { get; set; }
    public Fulfillmentmessage[] fulfillmentMessages { get; set; }
    public Intent intent { get; set; }
    public int intentDetectionConfidence { get; set; }
    public string languageCode { get; set; }
}

public class Parameters
{
    public string name { get; set; }
}

public class Intent
{
    public string name { get; set; }
    public string displayName { get; set; }
}

public class Fulfillmentmessage
{
    public Text text { get; set; }
}

public class Text
{
    public string[] text { get; set; }
}

public class Originaldetectintentrequest
{
    public Payload payload { get; set; }
}

public class Payload
{
}

这太棒了,因为我认为我花了 2-3 小时来制定原始代码来映射它,这几乎是即时的!:) 他推荐的网站也很有希望。

标签: c#jsonserializationdialogflow-es

解决方案


CodeReview StackExchange更适合这种情况,因为这主要是基于意见,使代码更可用,这是一个崇高的事业。

我要补充的一件事是,在 Visual Studio 中理解大型 Json 的一种好方法是创建一个新的 .cs 文件并将 Json 放在剪贴板中:编辑 > 选择性粘贴 > 将 Json 粘贴为类。关于起点非常方便。


推荐阅读