来自开放 API 的 .Net Parser JSON

问题描述

我正在做一个小项目来处理游戏中的一些大数据,这将使我能够查看一些高级分析,但是,我遇到了障碍...... 以下 URL (Click Here) 是返回 JSON 结果的开放 API,我正在尝试将其作为我自己的数据进行处理。

我创建了一个类来将这些数据处理到我的模型中,但是,每次调用第 5 行时 client.DownloadString 我都会收到错误 403,有什么办法可以解决这个问题吗? 我不知道 api 的所有者。

public IActionResult Index(object sender,EventArgs e)
{
    var model = new FresnoVm();
    WebClient client = new WebClient();
    string strPageCode = client.DownloadString("https://api.upx.world/bigdata/query?neighborhood=210&neighborhood=359&neighborhood=367&neighborhood=366&neighborhood=356&neighborhood=364&city=0&status=All&mintMin=0&mintMax=100000000&saleMin=0&saleMax=100000000&skip=0&fsa=All&sort=mint_price&ascOrDesc=1");
    dynamic dobj = JsonConvert.DeserializeObject<dynamic>(strPageCode);

    price = dobj["data"]["properties"]["sale_price_upx"].ToString();

    model.test = price;

    return View("~/Features/Fresno/Index.cshtml",model);
}

解决方法

虽然按照 this answer 中建议的 Borg8 to WebClient 403 Forbidden 添加 "User-Agent: Other"wb.Headers 已足以下载响应字符串,由于返回的字符串大约为 1.6MB,因此最好按照 Newtonsoft 的 Performance Tips: Optimize Memory Usage 中的建议直接从响应流中反序列化。

首先定义如下辅助方法:

public static class JsonExtensions
{
    public static T GetFromJson<T>(string url,JsonSerializerSettings settings = default)
    {
        var request = (HttpWebRequest)HttpWebRequest.Create(url);
        // User-Agent as suggested by this answer https://stackoverflow.com/a/6905471/3744182
        // by https://stackoverflow.com/users/873595/borg8
        // To https://stackoverflow.com/questions/3272067/webclient-403-forbidden
        request.UserAgent = "Other";

        using (var response = (HttpWebResponse)request.GetResponse())
        {
            if (response.StatusCode == HttpStatusCode.OK)
            {
                using (var stream = response.GetResponseStream())
                using (var textReader = new StreamReader(stream))
                {
                    settings = settings ?? new JsonSerializerSettings { CheckAdditionalContent = true };
                    return (T)JsonSerializer.CreateDefault(settings).Deserialize(textReader,typeof(T));
                }
            }
            else
            {
                throw new ApplicationException(); // Throw some exception with a message of your choice
            }
        }
    }
}

然后你可以这样做:

var dobj = JsonExtensions.GetFromJson<JToken>(url);
var prices = dobj["data"]["properties"].Select(t => (decimal?)t["last_paid_price_upx"]).ToList(); // Or cast to (string) if you prefer

注意事项:

  • 返回的 JSON 中没有名为 "sale_price_upx" 的属性。部分(但不是全部)data.properties[*] 对象包含 "last_paid_price_upx" 属性,因此上面的代码显示了如何将这些对象提取为可空小数的示例。

  • LINQ-to-JSON 文档对象模型可以为属性名称使用大量内存。将大量数据反序列化为直接包含您需要的属性的显式数据模型可能会获得更好的性能。

演示小提琴here

,

添加如下所示的简单行

wb.Headers.Add("User-Agent: Other");   //that is the simple line!