如何检查JSON数组是否是递归的对象或基元数组

时间:2018-12-06 10:41:33

标签: arrays json .net-core json.net

标题正是我的意思

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"
    }
]

1 个答案:

答案 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”