在 C# 中使用 Json.Parse 或 Regex 获取单行 JSON 响应

Posted

技术标签:

【中文标题】在 C# 中使用 Json.Parse 或 Regex 获取单行 JSON 响应【英文标题】:Obtaining single line of a JSON response, using either Json.Parse or Regex in C# 【发布时间】:2019-07-27 13:06:29 【问题描述】:

我是一名初级 Java 开发人员,对 C# 不太了解,所以我希望在解决问题方面得到一些帮助。我想要做的是使用 github 上共享的现有代码,该代码接受麦克风输入,将其上传到 Google Speech-to-Text API,然后返回带有脚本的 JSON 响应。这部分工作正常。

什么不起作用,将 JSON 中返回的“Transcript:”的值存储到字符串变量中。

我尝试过多种方式,我已经寻找使用 SimpleJSON 和 Newtonsoft 将 JSON 响应转换为对象的方法,并且我还尝试使用正则表达式来读取以“transcript.json”开头的 JSON 行。 "我看到了一个我想要完成的示例(链接如下),但我遇到了编译器错误。如果有人可以帮助我,或者指出更好的结果,我将不胜感激。

这是我正在使用的代码。

//从https://github.com/steelejay/LowkeySpeech获取

using UnityEngine;
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Web;


[RequireComponent(typeof(Audiosource))]

public class GoogleVoiceSpeech : MonoBehaviour 

    public GUIText TextBox;

    struct ClipData 
        public int samples;
    

    const int HEADER_SIZE = 44;

    private int minFreq;
    private int maxFreq;

    private bool micConnected = false;

    //A handle to the attached AudioSource
    private AudioSource goAudioSource;

    public string apiKey;

    // Use this for initialization
    void Start() 
        //Check if there is at least one microphone connected
        if (Microphone.devices.Length <= 0) 
            //Throw a warning message at the console if there isn't
            Debug.LogWarning("Microphone not connected!");
         else //At least one microphone is present
          
            //Set 'micConnected' to true
            micConnected = true;

            //Get the default microphone recording capabilities
            Microphone.GetDeviceCaps(null, out minFreq, out maxFreq);

            //According to the documentation, if minFreq and maxFreq are zero, the microphone supports any frequency...
            if (minFreq == 0 && maxFreq == 0) 
                //...meaning 44100 Hz can be used as the recording sampling rate
                maxFreq = 44100;
            

            //Get the attached AudioSource component
            goAudioSource = this.GetComponent<AudioSource>();
        
    

    void OnGUI() 
        //If there is a microphone
        if (micConnected) 
            //If the audio from any microphone isn't being recorded
            if (!Microphone.IsRecording(null)) 
                //Case the 'Record' button gets pressed
                if (GUI.Button(new Rect(Screen.width / 2 - 100, Screen.height / 2 - 25, 200, 50), "Record")) 
                    //Start recording and store the audio captured from the microphone at the AudioClip in the AudioSource
                    goAudioSource.clip = Microphone.Start(null, true, 7, maxFreq); //Currently set for a 7 second clip
                
             else //Recording is in progress
              

                //Case the 'Stop and Play' button gets pressed
                if (GUI.Button(new Rect(Screen.width / 2 - 100, Screen.height / 2 - 25, 200, 50), "Stop and Play!")) 
                    float filenameRand = UnityEngine.Random.Range(0.0f, 10.0f);

                    string filename = "testing" + filenameRand;

                    Microphone.End(null); //Stop the audio recording

                    Debug.Log("Recording Stopped");

                    if (!filename.ToLower().EndsWith(".wav")) 
                        filename += ".wav";
                    

                    var filePath = Path.Combine("testing/", filename);
                    filePath = Path.Combine(Application.persistentDataPath, filePath);
                    Debug.Log("Created filepath string: " + filePath);

                    // Make sure directory exists if user is saving to sub dir.
                    Directory.CreateDirectory(Path.GetDirectoryName(filePath));
                    SavWav.Save(filePath, goAudioSource.clip); //Save a temporary Wav File
                    Debug.Log("Saving @ " + filePath);
                    //Insert your API KEY here.
                    string apiURL = "https://speech.googleapis.com/v1/speech:recognize?&key=AIzaSyAV65cThBBZAqmzW7MbWaccybtBrwY4Udc";
                    string Response;

                    Debug.Log("Uploading " + filePath);
                    Response = HttpUploadFile(apiURL, filePath, "file", "audio/wav; rate=44100");
                    Debug.Log("Response String: " + Response);

                    var jsonresponse = SimpleJSON.JSON.Parse(Response);

                    if (jsonresponse != null) 
                        string resultString = jsonresponse["result"][0].ToString();
                        var jsonResults = SimpleJSON.JSON.Parse(resultString);

                        string transcripts = jsonResults["alternative"][0]["transcript"].ToString();

                        Debug.Log("transcript string: " + transcripts);
                        TextBox.text = transcripts;

                    
                    //goAudioSource.Play(); //Playback the recorded audio

                    File.Delete(filePath); //Delete the Temporary Wav file

                

                GUI.Label(new Rect(Screen.width / 2 - 100, Screen.height / 2 + 25, 200, 50), "Recording in progress...");
            
         else // No microphone
          
            //Print a red "Microphone not connected!" message at the center of the screen
            GUI.contentColor = Color.red;
            GUI.Label(new Rect(Screen.width / 2 - 100, Screen.height / 2 - 25, 200, 50), "Microphone not connected!");
        
    

    public string HttpUploadFile(string url, string file, string paramName, string contentType) 

        System.Net.ServicePointManager.ServerCertificateValidationCallback += (o, certificate, chain, errors) => true;
        Debug.Log(string.Format("Uploading 0 to 1", file, url));

        Byte[] bytes = File.ReadAllBytes(file);
        String file64 = Convert.ToBase64String(bytes,
                                         Base64FormattingOptions.None);

        Debug.Log(file64);

        try 

            var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
            httpWebRequest.ContentType = "application/json";
            httpWebRequest.Method = "POST";

            using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream())) 




                string json = " \"config\":  \"languageCode\" : \"en-US\" , \"audio\" :  \"content\" : \"" + file64 + "\"";

                Debug.Log(json);
                streamWriter.Write(json);
                streamWriter.Flush();
                streamWriter.Close();
            

            var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
            Debug.Log(httpResponse);

            using (var streamReader = new StreamReader(httpResponse.GetResponseStream())) 
                var result = streamReader.ReadToEnd();
                Debug.Log("Response:" + result);

            

        
        catch (WebException ex) 
            var resp = new StreamReader(ex.Response.GetResponseStream()).ReadToEnd();
            Debug.Log(resp);

        


        return "empty";

    


我正在使用 JSON 结果返回正确的控制台消息。我只需要将“成绩单”值转换为字符串。这是来自 Google API 的响应示例。

Response:
  "results": [
    
      "alternatives": [
        
          "transcript": "this is a test",
          "confidence": 0.98762906
        
      ]
    
  ]

SimpleJSON 框架的实际创建者几年前曾回应过有人遇到类似问题,但当我尝试实施类似修复时,我收到错误,因为我的回应是单一的。

https://answers.unity.com/questions/1443367/get-json-array-object-string-value.html

如果有人对此提供帮助或指导,我将不胜感激。我已经在网上寻找了几天试图让这个工作,并在发布之前询问了同事(由于他们对 C# 缺乏经验而无法帮助我)。

【问题讨论】:

有什么方法可以将其归结为minimal reproducible example,显示代码中的具体问题? 主要问题是如何从 json 中的替代数组中获取成绩单属性(字符串)? @Noel 是的,主要问题是如何从 Json 中的替代数组中获取脚本字符串。 (我可能在我的问题中提供了太多信息,但我想彻底)在示例中,成绩单上写着“这是一个测试”,我希望将其存储在一个变量中。 @dbc 部分问题是我不确定将我的代码正确放置在现有的哪个位置,这取决于我放入代码的方法,程序可能会锁定或返回 null。我发布的整个代码都成功地在控制台中显示了 Json,我要做的就是获取成绩单并将其存储在一个字符串中。 【参考方案1】:

Newtonsoft 是一个更好的选择,我将引导您了解如何使用它。

首先,create the C# classes 您需要保存解析结果。在您的示例中,它们将如下所示:

public class SpeechResponse

    public Result[] results  get; set; 


public class Result

    public Alternative[] alternatives  get; set; 


public class Alternative

    public string transcript  get; set; 
    public float confidence  get; set; 

您已经知道如何获取 JSON 数据,因此假设它已保存在 String json 中。您可以使用以下命令将字符串转换为 C# 类:

var response = JsonConvert.DeserializeObject<SpeechResponse>( json );

您正在寻找的特定数据可以这样获得:

string phrase = response.results[0].alternatives[0].transcript;

奖金提示 如果您使用的是 Visual Studio,则可以通过复制 JSON 示例数据并选择“编辑 -> 选择性粘贴 -> 将 JSON 粘贴为类” (Read More) 轻松创建类定义。

【讨论】:

非常感谢!这对我来说非常有效,我想使用 Newtonsoft 更容易。它比我尝试过的其他方法要干净得多。我投票给你,但因为我是菜鸟,所以不会影响公开评级。谢谢你教我一些东西! 不客气。如果它能让您将我的回答标记为“已接受”,这是让每个人都知道您的问题已解决的最佳方式。 完美,这是我的第一篇文章,所以学习这些东西很有帮助。

以上是关于在 C# 中使用 Json.Parse 或 Regex 获取单行 JSON 响应的主要内容,如果未能解决你的问题,请参考以下文章

关于vue中JSON.parse(JSON.stringify(...))使用深拷贝问题

在 C# 中循环一个 SimpleJSON 数组

安全地处理节点中的错误 JSON.parse()

JSON.stringify(),JSON.parse()

使用正则获取jsonp字符串里的json数据

node.js JSON.parse reviver 不报告重复键?