解码具有未知密钥的Json对象

本文关键字:Json 对象 密钥 未知 解码 | 更新日期: 2023-09-27 17:59:44

我有一个json对象,我不知道对象中的键是什么,有没有办法用Unity的JsonUtility解码这样的对象?

这是我所拥有的,但它不起作用:

[RequireComponent(typeof(Text))]
public class GameSmartTranslate : MonoBehaviour {
    public string translationKey;
    Text text;
    // Use this for initialization
    void Start () {
        text = GetComponent<Text>();
        GetTranslationFile();
    }
    void GetTranslationFile(){
        string lang = GameSmart.Web.Locale(true);
        TextAsset transFile = Resources.Load<TextAsset>("Text/" + lang);
        Trans items = JsonUtility.FromJson<Trans>(transFile.text);
    }
}
[System.SerializableAttribute]
class Trans {
    public string key;
    public string value;
}

测试json文件如下(文件密钥很可能不是onetwo):

{
    "one": "First Item",
    "two": "Second Item"
}

密钥为"未知"的原因是,这是一个用于翻译的json文件,由于每个游戏都有不同的游戏性,这意味着每个游戏的文本也不同,密钥的数量也不同。这也是为了一个我必须管理的sdk,它将被放入许多游戏中。

解码具有未知密钥的Json对象

根据您的评论,您真正需要的是两个级别的序列化,一个级别代表每个翻译的单词,另一个级别包含单词数组。

[Serializable]
public class Word{
    public string key;
    public string value;
}
[Serializable]
public class Translation 
{ 
     public Word[] wordList; 
}

这将被翻译成类似的JSON

{
   "wordList": [
      {
         "key": "Hello!",
         "value": "¡Hola!"
      },
      {
         "key": "Goodbye",
         "value": "Adiós"
      }
   ]
}

一旦反序列化了Translation对象,就可以将其转换为字典,以加快查找速度。

Translation items = JsonUtility.FromJson<Translation>(transFile.text);
Dictionary<string, string> transDict = items.wordList.ToDictionary(x=>x.key, y=>y.value);

通过使key是未翻译的单词,可以很容易地制定一种扩展方法,在字典中查找翻译后的单词,但如果找不到,就会使用key。

public static class ExtensionMethods
{
    public static string GetTranslationOrDefault(this Dictionary<string, string> dict, string word)
    {
        string result;
        if(!dict.TryGetValue(word, out result)
        {
            //Word was not in the dictionary, return the key.
            result = word;
        }
        return result;
    }
}

你可以像一样使用

[RequireComponent(typeof(Text))]
public class GameSmartTranslate : MonoBehaviour {
    public string translationKey;
    Text text;
    void Start() {
        text = GetComponent<Text>();
        Dictionary<string, string> transDict = GetTranslationFile();
        //If the translation is not defined the text is set to translationKey
        text.text = transDict.GetTranslationOrDefault(translationKey);
    }
    Dictionary<string, string> GetTranslationFile(){
        string lang = GameSmart.Web.Locale(true);
        TextAsset transFile = Resources.Load<TextAsset>("Text/" + lang);
        Translation items = JsonUtility.FromJson<Translation>(transFile.text);
        Dictionary<string, string> transDict = items.wordList.ToDictionary(x=>x.key, y=>y.value);
        return transDict;
    }
}

您可能想尝试将字典代码从GameSmartTranslate中移出,并将其放在一个单例游戏对象中,这样字典就不会为每个包含此脚本的标签重新构建。


更新:

您也可以尝试使用json

[{
    "key": "Hello!",
    "value": "¡Hola!"
}, {
    "key": "Goodbye",
    "value": "Adiós"
}]

这将使您摆脱Translation类,并且您的代码看起来像

Word[] items = JsonUtility.FromJson<Word[]>(transFile.text);

但我很确定Unity 5.3不能直接用于数组类型,我还没有尝试过5.4。