标题正是我的意思
Stackoverflow上的所有问题都询问json数据是对象还是数组,但是我要寻找的是查看是否可以确定该数组是原始类型或对象的数组。
目前,我已经可以确定它是否为数组,只是如果它不是字符串数组,我将无法进行转换。
此代码被包装在for循环中(在comArr中为var comArrEl),其中comArr是字符串数组。该数组存储类似于“ gesmes:Envelope:Cube:Cube:@ currency =“ USD”
基本上,我们正在尝试在此处编写通用API包装器。
// Identify if its an array or an object
if (token is JArray)
{
try
{
// Parse the comArrEl to an integer for index access
if (int.TryParse(comArrEl, out int index))
{
// Pump in the array
var dataList = token.ToObject<List<object>>();
// Is it the last?
if (comArrEl != last)
{
// let's work it out
// update the token
if (index >= 0 && index < dataList.Count)
{
token = JToken.Parse(JsonConvert.SerializeObject(dataList[index]));
}
}
// Yes its the last
else
{
var property = dataList[index];
// Number checks
// Make sure the datalist element we're targetting contains a proper value.
if (decimal.TryParse(property, out decimal val))
{
// Update it
_currencyPairComponentService.UpdatePairValue(component.Id, val);
}
}
}
// Incorrect comArrEl.
else
{
return false;
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
如您所见,异常在第2行触发。
样本有效负载代码:
[
{
"@currency": "USD",
"@rate": "1.1354"
},
{
"@currency": "JPY",
"@rate": "128.31"
},
{
"@currency": "BGN",
"@rate": "1.9558"
},
{
"@currency": "CZK",
"@rate": "25.886"
},
{
"@currency": "DKK",
"@rate": "7.4630"
},
{
"@currency": "GBP",
"@rate": "0.88885"
},
{
"@currency": "HUF",
"@rate": "323.49"
},
{
"@currency": "PLN",
"@rate": "4.2826"
},
{
"@currency": "RON",
"@rate": "4.6528"
},
{
"@currency": "SEK",
"@rate": "10.1753"
},
{
"@currency": "CHF",
"@rate": "1.1328"
},
{
"@currency": "ISK",
"@rate": "139.40"
},
{
"@currency": "NOK",
"@rate": "9.6480"
},
{
"@currency": "HRK",
"@rate": "7.3990"
},
{
"@currency": "RUB",
"@rate": "75.8385"
},
{
"@currency": "TRY",
"@rate": "6.0453"
},
{
"@currency": "AUD",
"@rate": "1.5569"
},
{
"@currency": "BRL",
"@rate": "4.3692"
},
{
"@currency": "CAD",
"@rate": "1.5076"
},
{
"@currency": "CNY",
"@rate": "7.7848"
},
{
"@currency": "HKD",
"@rate": "8.8695"
},
{
"@currency": "IDR",
"@rate": "16344.08"
},
{
"@currency": "ILS",
"@rate": "4.2293"
},
{
"@currency": "INR",
"@rate": "80.0660"
},
{
"@currency": "KRW",
"@rate": "1264.39"
},
{
"@currency": "MXN",
"@rate": "23.2282"
},
{
"@currency": "MYR",
"@rate": "4.7165"
},
{
"@currency": "NZD",
"@rate": "1.6398"
},
{
"@currency": "PHP",
"@rate": "59.878"
},
{
"@currency": "SGD",
"@rate": "1.5520"
},
{
"@currency": "THB",
"@rate": "37.190"
},
{
"@currency": "ZAR",
"@rate": "15.6366"
}
]
答案 0 :(得分:0)
此方法可以动态地迭代JSON结果(无论是对象还是原始)。该方法遍历名为 requestComponents 的数组,该数组定义了我们要从JSON有效负载中获取的属性。
然后将每个requestComponent字符串分解为一个数组(即“ gesmes:Envelope / Cube / Cube / Cube / 0 => @ rate”),以使我们可以遍历对象/数组。有时是一个数组,有时是一个对象,我们可以轻松地走这条路。仅适用于requestComponent数组的最后一个元素的自定义“ =>”语法将告诉代码检索该属性。 (样本:0 => @ currency //这将告诉我们获取索引为0的对象,即“ @currency”属性)
这是代码,不关注输入,而是逻辑。这里的重点是在处理它之前先查看即将到来的属性,以查看其是否为数组等。因此您的目标可能是
object/array/object/array/array element index
或者也可以是
array/object/array/object/property
瞧
ResponseType是一个Enum,RequestComponents是一个包含要遍历的字符串的对象(这是该对象中所有重要的东西),令牌基本上是json负载。
public bool Update(JToken token, ResponseType resType, IEnumerable<RequestComponent> requestComponents)
{
// For each component we're checking
foreach (var component in requestComponents)
{
var comArr = component.QueryComponent.Split("/"); // Split the string if its nesting
var last = comArr.LastOrDefault(); // get the last to identify if its the last
// Iterate the queryComponent Array
foreach (var comArrEl in comArr)
{
// Null check
if (comArrEl != null)
{
// CHECK CURRENT TYPE
// Identify if its an array or an object
if (token is JArray)
{
try
{
// Is it the last?
if (comArrEl != last)
{
// Parse the comArrEl to an integer for index access
if (int.TryParse(comArrEl, out int index))
{
// Pump in the array, treat it as anonymous.
var dataList = token.ToObject<List<JObject>>();
// let's work it out
// update the token
if (index >= 0 && index < dataList.Count)
{
// Traverse the array
token = JToken.Parse(JsonConvert.SerializeObject(dataList[index]));
}
}
}
// Yes its the last
else
{
// See if theres any property we need to refer to.
var comArrElArr = comArrEl.Split("=>");
if (int.TryParse(comArrElArr[0], out var index))
{
// Traverse first
var rawData = token.ToObject<List<JToken>>()[index];
// if its 1, we assume its just an array of a primitive type
if (comArrElArr.Length == 1)
{
// Retrieve the value.
var rawVal = rawData.ToString();
// https://stackoverflow.com/questions/23131414/culture-invariant-decimal-tryparse
var style = NumberStyles.Any;
if (ExponentHelper.IsExponentialFormat(rawVal))
{
style = NumberStyles.Float;
}
// If it is an exponent
if (decimal.TryParse(rawVal, style, CultureInfo.InvariantCulture,
out var val))
{
if (val > 0)
{
// Update it
_currencyPairComponentService.UpdatePairValue(component.Id, val);
}
}
}
// Oh no.. non-primitive...
else if (comArrElArr.Length == 2)
{
// Object-ify
var rawObj = JObject.Parse(rawData.ToString());
// Obtain the desired value
var rawVal = rawObj[comArrElArr[1]].ToString();
// As usual, update it
// https://stackoverflow.com/questions/23131414/culture-invariant-decimal-tryparse
var style = NumberStyles.Any;
if (ExponentHelper.IsExponentialFormat(rawVal))
{
style = NumberStyles.Float;
}
// If it is an exponent
if (decimal.TryParse(rawVal, style, CultureInfo.InvariantCulture,
out var val))
{
if (val > 0)
{
// Update it
_currencyPairComponentService.UpdatePairValue(component.Id, val);
}
}
}
else
{
// Invalid
return false;
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
else if (token is JObject)
{
// Pump in the object
JObject obj = token.ToObject<JObject>();
// Is it the last?
if (comArrEl != last)
{
// let's work it out
// update the token
token = obj.SelectToken(comArrEl);
}
// Yes its the last
else
{
// See if theres any property we need to refer to.
var comArrElArr = comArrEl.Split("=>");
// Traverse first
var rawData = (string) obj.SelectToken(comArrElArr[0]);
if (rawData != null)
{
// if its 1, we assume its just an array of a primitive type
if (comArrElArr.Length == 1)
{
// Retrieve the value.
var rawVal = rawData.ToString();
// https://stackoverflow.com/questions/23131414/culture-invariant-decimal-tryparse
var style = NumberStyles.Any;
if (ExponentHelper.IsExponentialFormat(rawVal))
{
style = NumberStyles.Float;
}
// If it is an exponent
if (decimal.TryParse(rawVal, style, CultureInfo.InvariantCulture,
out var val))
{
if (val > 0)
{
// Update it
_currencyPairComponentService.UpdatePairValue(component.Id, val);
}
}
}
// Oh no.. non-primitive...
else if (comArrElArr.Length == 2)
{
// Object-ify
var rawObj = JObject.Parse(rawData.ToString());
// Obtain the desired value
var rawVal = rawObj[comArrElArr[1]].ToString();
// As usual, update it
// https://stackoverflow.com/questions/23131414/culture-invariant-decimal-tryparse
var style = NumberStyles.Any;
if (ExponentHelper.IsExponentialFormat(rawVal))
{
style = NumberStyles.Float;
}
// If it is an exponent
if (decimal.TryParse(rawVal, style, CultureInfo.InvariantCulture,
out var val))
{
if (val > 0)
{
// Update it
_currencyPairComponentService.UpdatePairValue(component.Id, val);
}
}
}
else
{
// Invalid
return false;
}
}
}
}
// iterate JValue like a JObject
else if (token is JValue)
{
// Pump in the object
JObject obj = token.ToObject<JObject>();
// Is it the last?
if (comArrEl != last)
{
// let's work it out
// update the token
token = obj.SelectToken(comArrEl);
}
// Yes its the last
else
{
var rawData = (string) obj.SelectToken(component.QueryComponent);
if (rawData != null)
{
// https://stackoverflow.com/questions/23131414/culture-invariant-decimal-tryparse
var style = NumberStyles.Any;
if (ExponentHelper.IsExponentialFormat(rawData))
{
style = NumberStyles.Float;
}
// If it is an exponent
if (decimal.TryParse(rawData, style, CultureInfo.InvariantCulture,
out decimal val))
{
if (val > 0)
{
// Update it
_currencyPairComponentService.UpdatePairValue(component.Id, val);
}
}
}
}
}
}
else
{
// Something bad happened
return false;
}
}
}
return false;
}
什么类型的数据输入有效?
好吧,“令牌”属性可以是这个
{
"?xml": {
"@version": "1.0",
"@encoding": "UTF-8"
},
"gesmes:Envelope": {
"@xmlns:gesmes": "http://www.gesmes.org/xml/2002-08-01",
"@xmlns": "http://www.ecb.int/vocabulary/2002-08-01/eurofxref",
"gesmes:subject": "Reference rates",
"gesmes:Sender": {
"gesmes:name": "European Central Bank"
},
"Cube": {
"Cube": {
"@time": "2018-12-06",
"Cube": [
{
"@currency": "USD",
"@rate": "1.1351"
},
{
"@currency": "JPY",
"@rate": "128.04"
},
{
"@currency": "BGN",
"@rate": "1.9558"
},
{
"@currency": "CZK",
"@rate": "25.890"
},
{
"@currency": "DKK",
"@rate": "7.4635"
},
{
"@currency": "GBP",
"@rate": "0.88930"
},
{
"@currency": "HUF",
"@rate": "323.75"
},
{
"@currency": "PLN",
"@rate": "4.2881"
},
{
"@currency": "RON",
"@rate": "4.6548"
},
{
"@currency": "SEK",
"@rate": "10.2355"
},
{
"@currency": "CHF",
"@rate": "1.1304"
},
{
"@currency": "ISK",
"@rate": "138.40"
},
{
"@currency": "NOK",
"@rate": "9.7028"
},
{
"@currency": "HRK",
"@rate": "7.3965"
},
{
"@currency": "RUB",
"@rate": "75.9421"
},
{
"@currency": "TRY",
"@rate": "6.0947"
},
{
"@currency": "AUD",
"@rate": "1.5745"
},
{
"@currency": "BRL",
"@rate": "4.4370"
},
{
"@currency": "CAD",
"@rate": "1.5229"
},
{
"@currency": "CNY",
"@rate": "7.8239"
},
{
"@currency": "HKD",
"@rate": "8.8669"
},
{
"@currency": "IDR",
"@rate": "16481.65"
},
{
"@currency": "ILS",
"@rate": "4.2367"
},
{
"@currency": "INR",
"@rate": "80.4950"
},
{
"@currency": "KRW",
"@rate": "1273.03"
},
{
"@currency": "MXN",
"@rate": "23.3643"
},
{
"@currency": "MYR",
"@rate": "4.7271"
},
{
"@currency": "NZD",
"@rate": "1.6517"
},
{
"@currency": "PHP",
"@rate": "60.012"
},
{
"@currency": "SGD",
"@rate": "1.5560"
},
{
"@currency": "THB",
"@rate": "37.282"
},
{
"@currency": "ZAR",
"@rate": "15.9797"
}
]
}
}
}
}
更新方法:第6行需要输入样本吗?
这将获得@rate属性。
gesmes:Envelope/Cube/Cube/Cube/0=>@rate
更简单的示例:
[
97.935,
1745.41815607,
97.936,
315.65150703,
-6.58,
-0.063,
97.93,
664801.20661302,
105.67,
96.23
]
第6行只是“ 0”