2016-08-02 133 views
1

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

这里是我有什么,但它不工作:

[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,它将被放入许多游戏中。

+0

您是否真的不知道模式是什么,或者您知道“如果属性'X'具有'Foo'的值,那么我知道json描述了一个'Foo'对象,并且可以将其作为一个对象进行去除处理,或者你有一系列物品,但你不知道该数组中会有多少物品。这是非常罕见的,你会*不知道*输入是什么。 –

+0

@ScottChamberlain我不知道密钥的原因是因为我正在管理许多游戏的sdk,并且每个游戏都需要翻译,因此每个项目都有一个密钥(一个用于翻译的标识符,比如'score')和一个值(翻译后的文字,如“Score”或“得分了”或“Гол”)。由于每场比赛都不同,所有的键也会不同。 –

回答

2

根据您的意见,您真正需要的是两个级别的序列化,一个级别代表每个翻译的单词,另一个级别代表单词阵列。

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

[Serializable] 
public class Translation 
{ 
    public Word[] wordList; 
} 

这会转换到JSON一旦反序列化对象Translation你可以将其转换为一个字典快速查找看起来类似于

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

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

通过使关键的未转换的话,很容易使一个扩展方法,将查找在字典中的译词,但如果它不能找到一个它将使用的关键。

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来试过。

+0

这是有点我在做什么,所以没有办法没有一个对象的数组呢? –

+0

你需要某种可预测的结构。你可以尝试一个简单的数组(参见我的更新),但我不知道unity是否支持直接或不是直接数组。 –

+0

从我读过的根项目需要成为一个对象。 –