从网络请求响应中解析 json

Parse json from web request response

我正在尝试将 http 网络响应解析为数组或其他内容,以便我可以处理这些信息。这是我得到的 json 回复(+ 很多,但我只是审查了格式):

{
    "meta": {
        "status": 200
    },
    "data": {
        "account": {
            "account_phone_number": "XXXXXXXX",
            "account_email": "MAIL@hotmail.com"
        },
        "user": {
            "id": "5f2b17e7836fc7010025aed3",
            "age": 23,
        }
    }
}

如何将“用户”中的“id”写入控制台或文本框?

这是我的网络请求:

private void button1_Click(object sender, EventArgs e)
{
    const string WEBSERVICE_URL = "url_here";
    try
    {
        var webRequest = System.Net.WebRequest.Create(WEBSERVICE_URL);
        if (webRequest != null)
        {
            webRequest.Method = "GET";
            webRequest.Timeout = 12000;
            webRequest.ContentType = "application/json";
            webRequest.Headers.Add("x-auth-token", "Auth_token");

            using (System.IO.Stream s = webRequest.GetResponse().GetResponseStream())
            {
                using (System.IO.StreamReader sr = new System.IO.StreamReader(s))
                {
                    var jsonResponse = sr.ReadToEnd();
                    richTextBox1.AppendText(jsonResponse);
                }
            }
        }
    }
    catch (Exception ex)
    {
        richTextBox1.AppendText("No workie");
    }
}

我尝试了以下方法:

public class Test
{
   public string meta {get;set;}
   public string data {get;set;}
}

并尝试将 json 序列化为 table,如下所示:

JavaScriptSerializer js = new JavaScriptSerializer();
Test[] Tester = js.Deserialize<Test[]>(jsonResponse);
richTextBox1.AppendText(Tester);

但运气不好。谁能给我指出正确的方向吗?

除了您的 测试 Class

之外,一切都是正确的

对于复杂的 JSON 使用 https://json2csharp.com/ 将 Json 转换为 C# Class

public class Meta    {
    public int status { get; set; } 
}

public class Account    {
    public string account_phone_number { get; set; } 
    public string account_email { get; set; } 
}

public class User    {
    public string id { get; set; } 
    public int age { get; set; } 
}

public class Data    {
    public Account account { get; set; } 
    public User user { get; set; } 
}

public class Root    {
    public Meta meta { get; set; } 
    public Data data { get; set; } 
}

然后使用这个

JavaScriptSerializer js = new JavaScriptSerializer();
var Root = js.Deserialize<Root>(jsonResponse);

如果您能够使用 JavaScriptSerializer 以外的其他序列化程序,那么您可以利用部分反序列化。

如果是 Json.NET(以前称为 Newtonsoft Json),您至少有两个选择:

SelectToken

JObject semiParsedData = JObject.Parse(jsonResponse);
string id = (string)semiParsedData.SelectToken("data.user.id");
int age = (int)semiaParsedData.SelectToken("data.user.age");
string email = (string)semiParsedData.SelectToken("data.account.account_email");
  • 通过调用 Parse 方法,我们将得到一个半解析的对象。
  • 在这个对象上我们可以发出 Json Path query via the SelectToken
    • 语法类似于XPath,可用于检索任何 任意数据形成 XML.
    • 更准确地说,它是
  • SelectTokenreturns一个JToken。您可以通过多种方式从中检索数据:
    • (string)semiParsedData.SelectToken("data.user.id")
    • semiParsedData.SelectToken("data.user.id").Value<string>()
    • semiParsedData.SelectToken("data.user.id").ToObject<string>()

参考文献:

indexer operator

JObject semiParsedData = JObject.Parse(jsonResponse);
JToken data = semiParsedData["data"];

JToken user = data["user"];
string id = (string)user["id"];
int age = (int)user["age"];

JToken account = data["account"];
string email = (string)account["account_email"];
  • JToken 定义了以下索引器运算符,它并不是很有用:
public virtual JToken? this[object key]
{
    get => throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType()));
    set => throw new InvalidOperationException("Cannot set child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType()));
}
  • 另一方面,其派生的 class JObject 覆盖了它以使该功能有用:
    • JObject 派生自 JContainer,后者派生自 JToken)。
public JToken? this[string propertyName]
{
    get
    {
        ValidationUtils.ArgumentNotNull(propertyName, nameof(propertyName));
        JProperty? property = Property(propertyName, StringComparison.Ordinal);
        return property?.Value;
    }
    set
    {
        JProperty? property = Property(propertyName, StringComparison.Ordinal);
        if (property != null)
        {
            property.Value = value!;
        }
        else
        {
#if HAVE_INOTIFY_PROPERTY_CHANGING
            OnPropertyChanging(propertyName);
#endif
            Add(propertyName, value);
            OnPropertyChanged(propertyName);
        }
    }
}
  • 此处 Property 方法尝试从 _properties 集合中获取请求的实体:
    • private readonly JPropertyKeyedCollection _properties

参考: