通过字符串名称从JSON中获取属性(已反序列化为类)

3
我正在使用免费账户的货币转换API:https://currencylayer.com/documentation。我让用户输入输出货币,例如如果用户输入SGD,则会显示USD转换为SGD的货币转换率:"USDSGD":1.318504。 抓取该值的方法是使用动态反序列化器,将其放入标签中,如下所示:
   lblResult.Text=test.quotes.USDSGD.ToString();

但我想要的是不考虑用户选择的货币,获取结果。另一个货币总是美元,因此我想将其与用户输入的货币组合起来,从API获取正确的价值,如:

var propertyName = "USD" + destinationCurrencyName; // "USDSGD"
lblResult.Text=test.quotes.{propertyName}; // what I'd like

我需要访问“USDSGD”属性。

我知道可以使用反射(在C#中使用反射从字符串获取属性值),但那似乎有些复杂。

这是查询返回的内容:

{
  "success":true,
  "terms":"https:\/\/currencylayer.com\/terms",
  "privacy":"https:\/\/currencylayer.com\/privacy",
  "timestamp":1517629571,
  "source":"USD",
  "quotes":{
    "USDSGD":1.318504
  }
}

这是我的代码 - 强类型版本确实产生了预期的结果,但我想从文本框中读取货币的名称(实际上是quotes元素的属性名称):
protected void btnConvert_Click(object sender, EventArgs e)
{
    string convertTo = TextBox1.Text.ToString();
    var webRequest = (HttpWebRequest)WebRequest.Create("http://apilayer.net/api/live?access_key=MY_ACCESS_KEY&currencies=" + Server.UrlEncode(convertTo) + "&source=USD&format=1");
    var webResponse = (HttpWebResponse)webRequest.GetResponse();
    if (webResponse.StatusCode == HttpStatusCode.OK)
    {
        JavaScriptSerializer json = new JavaScriptSerializer();
        StreamReader sr = new StreamReader(webResponse.GetResponseStream());
        var resString = sr.ReadToEnd();
        //var test = JsonConvert.DeserializeObject<Result>(resString);
        //lblResult.Text=test.quotes.USDSGD.ToString();
        var test2 = JsonConvert.DeserializeObject<dynamic>(resString);
        lblResult.Text = test2.quotes.USD+convertTo;
    }
}

目前我的代码
var test2 = JsonConvert.DeserializeObject<dynamic>(resString);
        lblResult.Text = test2.quotes.USD+convertTo;

返回值:

SGD

由于"convertTo"变量的值为"SGD",因此返回了"SGD"。
我希望代码执行lblResult.Text = test2.quotes.USD+convertTo;,而不是返回"convertTo"变量。请注意保留HTML标签。

您的输入数据没有属性 USD,而且根据之前的编写方式,您使用了 USDSGD.ToString(),那么为什么现在不继续使用呢? - Sami Kuhmonen
@SamiKuhmonen 查询URL的格式如下: "http://apilayer.net/api/live?access_key=MY_ACCESS_KEY&currencies=" + Server.UrlEncode(convertTo) + "&source=USD&format=1"其中,"convertTo"是用户可以更改的变量,USD是常量。 最终,我想要得到的是 lblResult.Text=test.quotes.USDSGD.ToString(); 但是, 使用以下代码却无法实现: lblResult.Text=test.quotes.USD+convertTo.ToString(); - Tix
是的,这与你得到的结果无关。使用调试器。看看你说过能工作的代码的顶部代码。然后看看你现在使用但不能工作的代码。没有 USD 属性,所以当然会得到空值和 convertTo 作为输出。 - Sami Kuhmonen
但是如果你想获取“USDSGD”的值,就不要使用动态类型。请使用JObject。 - Sami Kuhmonen
2个回答

5

现在我理解了你的问题,你正在尝试将字符串连接起来以访问一个值,而不是连接值和货币。

dynamic 无法做到这一点,也没有必要。反序列化为 JObject 并使用它的属性来获取值:

var test2 = JObject.Parse(resString);
var value = (test2[“quotes”] as JObject)[“USD” + convertTo];

请注意,此操作并不检查数据的有效性。 value 是一个 JToken ,您可以从中获取值。

1
既然你已经理解了问题,能否请你修改一下问题,使其与你接受的答案相匹配?(或者更新答案以澄清它如何与标题中明显存在的ASP.Net相关) - Alexei Levenkov
1
@AlexeiLevenkov 好主意,我稍微编辑了一下,希望现在更清楚他们想要什么。 - Sami Kuhmonen

2
你需要使用 JObject 来遍历响应对象:
var response = JObject.Parse(resString);
var quotes = response["quotes"];
lblResult.Text = quotes[ "USD" + convertTo ].Value<string>().ToString();
< p > JObject 的索引器允许您直接使用字符串进行索引,这使您能够动态选择用户想要的正确属性。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接