在Newtonsoft.Json.Linq中使用Jobject解析多个对象



我正在尝试解析从谷歌语音到文本API的结果。json 响应是:

{"result":[]}
{"result":[
          {"alternative":[
                         {"transcript":"hello Google how are you     feeling","confidence":0.96274596},
                         {"transcript":"hello Google how are you today","confidence":0.97388196},
                         {"transcript":"hello Google how are you picking","confidence":0.97388196},
                         {"transcript":"hello Google how are you kidding","confidence":0.97388196}
                         ]
         ,"final":true}]
,"result_index":0
}

现在我正在尝试通过 JObject 解析它。解析出现两次的结果对象时出现问题,因此如何解析第二个结果对象。这是我正在尝试的代码:

              StreamReader SR_Response = new StreamReader(HWR_Response.GetResponseStream());
              Console.WriteLine(SR_Response.ReadToEnd()+SR_Response.ToString());
              String json_response = SR_Response.ReadToEnd() + SR_Response.ToString();
              JObject joo = JObject.Parse(json_response);
              JArray ja = (JArray)joo["result"];
                        foreach (JObject o in ja)
                        {
                            JArray ja2 = (JArray)o["alternative"];
                            foreach (JObject h in ja2)
                            {
                                Console.WriteLine(h["transcript"]);
                            }
                        }

我尝试使用反序列化目标代码的下一个解决方案是:

                string responseFromServer = (SR_Response.ReadToEnd());
                String[] jsons = responseFromServer.Split('n');
                String text = "";
                foreach (String j in jsons)
                {
                    dynamic jsonObject = JsonConvert.DeserializeObject(j);
                    if (jsonObject == null || jsonObject.result.Count <= 0)
                    {
                        continue;
                    }
                    Console.WriteLine((string)jsonObject["result"]["alternative"][0]["transcript"]);
                    text = jsonObject.result[0].alternative[0].transcript;
                }
                Console.WriteLine("MESSAGE : "+text); 

您拥有的是一系列 JSON 根对象,它们连接在一起形成一个流。 如使用 JsonReader 读取多个片段中所述,可以通过设置 JsonReader.SupportMultipleContent = true 来反序列化此类流。 因此,要反序列化流,应首先引入以下扩展方法:

public static class JsonExtensions
{
    public static IEnumerable<T> DeserializeObjects<T>(Stream stream, JsonSerializerSettings settings = null)
    {
        var reader = new StreamReader(stream); // Caller should dispose
        return DeserializeObjects<T>(reader, settings);
    }
    public static IEnumerable<T> DeserializeObjects<T>(TextReader textReader, JsonSerializerSettings settings = null)
    {
        var ser = JsonSerializer.CreateDefault(settings);
        var reader = new JsonTextReader(textReader); // Caller should dispose
        reader.SupportMultipleContent = true;
        while (reader.Read())
        {
            if (reader.TokenType == JsonToken.None || reader.TokenType == JsonToken.Undefined || reader.TokenType == JsonToken.Comment)
                continue;
            yield return ser.Deserialize<T>(reader);
        }
    }
}

接下来,使用代码生成实用程序(如 http://json2csharp.com/)为单个 JSON 根对象生成 c# 类,如下所示:

public class Alternative
{
    public string transcript { get; set; }
    public double confidence { get; set; }
}
public class Result
{
    public List<Alternative> alternative { get; set; }
    public bool final { get; set; }
}
public class RootObject
{
    public List<Result> result { get; set; }
    public int result_index { get; set; }
}

并按如下方式反序列化:

List<RootObject> results;
using (var stream = HWR_Response.GetResonseStream())
{
    results = JsonExtensions.DeserializeObjects<RootObject>(stream).ToList();
}

完成此操作后,可以使用标准 C# 编程技术(如 Linq)枚举transcript值,例如:

var transcripts = results
    .SelectMany(r => r.result)
    .SelectMany(r => r.alternative)
    .Select(a => a.transcript)
    .ToList();

如果不想为 JSON 集合定义固定数据模型,可以直接反序列化为JObject列表,如下所示:

List<JObject> objs;
using (var stream = HWR_Response.GetResonseStream())
{
    objs = JsonExtensions.DeserializeObjects<JObject>(stream).ToList();
}

然后,可以使用SelectTokens()选择嵌套在每个对象中的所有"transcript"属性的值:

var transcripts = objs
    // The following uses the JSONPath recursive descent operator ".." to pick out all properties named "transcript".
    .SelectMany(o => o.SelectTokens("..transcript")) 
    .Select(t => t.ToString())
    .ToList();

更新了显示这两个选项的示例小提琴。

相关内容

  • 没有找到相关文章

最新更新