繁体   English   中英

如何从复杂的json对象获取和返回键值?

[英]How do I get and return a key value from a complex json object?

我有一个Discord机器人,可以从JSON文件中获取密钥,并根据用户输入的命令返回值。 我希望能够访问复杂的JSON键(如“ charQuote”)并返回关联值(即“此处的视频游戏角色引号”)。

{
"characterKey": 
{
"charName":"Video Game character name here",
"charQuote": "Video Game character quote here", 
"charImageURL": "Video Game character image url here"
}

//I omitted 11 other complex objects that are similar to this one
}

其他答案如:

如何在C#.NET中反序列化复杂的JSON对象?

如何从带有Json Object的嵌套对象中获取Key并返回数组?

如何从json对象获取密钥并转换为数组?

...反序列化并将复杂对象和/或键作为数组返回。 但是我想从一个复杂的对象返回一个键值。

在这里,我有一个用简单的JSON对象管理单独的JSON文件的类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.IO;

namespace discordbot.Modules
{
    class Utilities
    {
        private static Dictionary<string, string> alerts;
        private const string File_Path = "json files/alerts.json";

        static Utilities()
        {
            string json = File.ReadAllText(File_Path);
            var data = JsonConvert.DeserializeObject<dynamic>(json);
            alerts = data.ToObject<Dictionary<string, string>>();          
        }

        public static string GetAlert(string key) //"hello" == key
        {
            if (alerts.ContainsKey(key))
                return alerts[key]; //returns "Hello World" which is the value
            return "";
        }

此类从输入的键返回值。 将使用此类的示例异步任务方法为:

[Command("test")]
        public async Task HelloWorldAsync(string hello = "hello")
        {
            await ReplyAsync(Utilities.GetAlert(hello));
        }

这是与包含复杂对象的JSON文件关联的类。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.IO;

namespace discordbot.Modules
{
    public static class CharacterUtilities 
    {

        //private static List<Dictionary<string, string>> QuoteAndPicture = new List<Dictionary<string, string>>();
        private static Dictionary<string, string> QuoteAndPicture = new Dictionary<string, string>();

        private const string File_Path = "json files/quotesandimages.json";

        static CharacterUtilities()
        {
            if(!File.Exists(File_Path))
            {
                File.WriteAllText(File_Path, "");
            }

            string json = File.ReadAllText(File_Path); 
            var data = JsonConvert.DeserializeObject<dynamic>(json);
            QuoteAndPicture = data.ToObject<Dictionary<string, string>>();

        }

        public static string GetQuoteImageName(string key) 
        {                        
            if (QuoteAndPicture.ContainsKey(key)))
                return QuoteAndPicture[key];
            return "";
        }

异步方法调用GetQuoteImageName

[Command("ex")] [RequireOwner]
        public async Task CharacterAsync(string characterContext)
        {                   
            await ReplyAsync(CharacterUtilities.GetQuoteImageName(characterContext)); 
        }

现在,如果我调用GetQuoteImageName方法,则会收到错误: The type initializer for 'discordbot.Modules.CharacterUtilities' threw an exception.

因此,我想知道是否有类似的方法可以从复杂对象而不是所有复杂值返回奇异值,类似于上面的第一类。

这将基于keysToSearchThrough搜索json。

        var data = JsonConvert.DeserializeObject<dynamic>(jsonString);
        // The keys you have to search through.
        string[] keysToSearchThrough = new string[] { "characterKey", "charName" };

        string result = string.Empty;

        // The current data it is travesing through
        Dictionary<string, dynamic> currTraversedData = data.ToObject<Dictionary<string, dynamic>>();

        for (int i = 0; i < keysToSearchThrough.Length; ++i) {

            if (currTraversedData.ContainsKey(keysToSearchThrough[i])) {
                // Get the value if the key current exists
                dynamic currTravesedDataValue = currTraversedData[keysToSearchThrough[i]];

                // Check if this 'currTravesedDataValue' can be converted to a 'Dictionary<string, dynamic>'
                if (IsStringDynamicDictionary(currTravesedDataValue)) {
                    // There is still more to travese through
                    currTraversedData = currTravesedDataValue.ToObject<Dictionary<string, dynamic>>();
                } else {
                    // There is no more to travese through. (This is the result)
                    result = currTravesedDataValue.ToString();

                    // TODO: Some error checking in the event that we reached the result early, even though we still have more keys to travase through
                    break;
                }

            } else {
                // One of the keys to search through was probably invalid.
            }
        }

        // ...

        bool IsStringDynamicDictionary(dynamic input) {
            try {
                input.ToObject<Dictionary<string, dynamic>>();
                return true;
            } catch (Exception) {
                return false;
            }
        }

最初,它将json数据转换为Dictionary<string, dynamic>

我们之所以具有dynamic ,是因为在任何给定时间点, Value都可以是stringDictionary<string, string>

然后,我们遍历keysToSearchThrough ,检查密钥是否存在于当前遍历的字典中。

如果键确实存在,则我们检查当前遍历字典的值是否为Dictionary<string, dynamic>

如果是的话,那意味着我们将有更多需要遍历的地方。
如果没有,那意味着我们可能已经走到了尽头。


"charName":"Character name"ValueString的类型。 这标志着我们到达了终点。
"charName": "Character name", "charQuote": "Character Quote"Value将是Dictionary<string, dynamic> 这标志着我们仍然可以遍历数据。

如果不够明显,则主要缺点是此代码看起来确实很凌乱。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM