如何检查JSON数组是否是递归的对象或基元数组 [英] How do you check if a JSON array is an array of objects or primitives recursively

查看:183
本文介绍了如何检查JSON数组是否是递归的对象或基元数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

标题正是我的意思

Stackoverflow上的所有问题都询问json数据是对象还是数组,但是我要寻找的是查看是否可以确定该数组是原始类型或对象的数组.

All the questions on Stackoverflow asks for whether if the json data is an object or array but what I'm looking for is to see if I can find out if the array is an array of primitive types or objects.

目前,我已经可以确定它是否为数组,只是如果它不是字符串数组,我将无法进行转换.

Currently, i already can identify if its an array or not, just that I'm unable to convert if it is not an array of strings.

此代码被包装在for循环中(在comArr中为var comArrEl),其中comArr是字符串数组.该数组存储的内容类似于"gesmes:Envelope:Cube:Cube:@ currency ="USD"

This code is wrapped in a for loop, where it is (var comArrEl in comArr), where comArr is an array of strings. This array stores something like "gesmes:Envelope:Cube:Cube:@currency="USD"

基本上,我们正在尝试在此处编写通用API包装器.

Basically we're trying to write a universal API wrapper here.

// 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行触发.

As you can see, the exception triggers on line 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"
    }
]

推荐答案

此方法可以动态迭代JSON结果(无论是对象还是原始).该方法遍历名为 requestComponents 的数组,该数组定义了我们想要从JSON有效负载中获取的属性.

This method can dynamically iterate a JSON result, be it object or primitive. This method loops through an array called requestComponents , which defines the properties we want to obtain from the JSON payload.

然后将每个requestComponent字符串分解为一个数组(即"gesmes:Envelope/Cube/Cube/Cube/0 => @ rate"),以使我们可以遍历该对象/数组.有时它是一个数组,有时是一个对象,我们可以很容易地走这条路.仅适用于requestComponent数组的最后一个元素的自定义"=>"语法将告诉代码检索该属性. (样本:0 => @ currency//这将告诉我们获取索引为0的对象,即"@currency"属性)

It then breaks down each requestComponent string into an array (i.e. "gesmes:Envelope/Cube/Cube/Cube/0=>@rate") to allow us to go down the object/array. Sometimes its an array, sometimes its an object, we can easily go down that path. A custom "=>" syntax that only works for the last element of the requestComponent array will tell the code to retrieve that property. (sample: 0=>@currency // That will tell us to obtain the object of index 0, the "@currency" property)

这是代码,不关注输入,而是逻辑.这里的重点是在处理即将到来的属性之前先查看它是否为数组等.因此您的目标可能是

Here's the code, do not focus on the inputs, but rather the logic. The main point here is to peek into the upcoming property to see if its an array or etc before processing it. So your target could be

object/array/object/array/array element index

或者也可以是

array/object/array/object/property

ResponseType是一个Enum,RequestComponents是一个包含要遍历的字符串的对象(这是该对象中所有重要的东西),令牌基本上是json负载.

ResponseType is an Enum, RequestComponents is an object that contains the string to traverse (That's all that matters in that object tbh) and token is basically the json payload.

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;
}

什么类型的数据输入有效?

What type of data input works?

好吧,令牌"属性可以是这个

well, the 'token' property can be this

{
  "?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行需要输入样本吗?

Update method: need a sample input for line 6?

这将获取@rate属性.

This will obtain the @rate property.

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"

这篇关于如何检查JSON数组是否是递归的对象或基元数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆