Reputation: 36351
I have a json object, and I have no idea what the keys in the object will be, is there a way to decode an object like this with Unity's JsonUtility?
Here is what I have, but it doesn't work:
[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;
}
The test json file looks like this (the files keys will more than likely not be one
and two
):
{
"one": "First Item",
"two": "Second Item"
}
The reason the keys are "Unknown" is because this is a json file for translations, and since each game has different gameplay it means the text is different in each game as well, and the number of keys will be different as well. This is also for an sdk that I have to manage that will be put into many games.
Upvotes: 1
Views: 3009
Reputation: 127603
Based on your comments what you really need is two levels of serialization, one level that represents each translated word and another that holds the array of words.
[Serializable]
public class Word{
public string key;
public string value;
}
[Serializable]
public class Translation
{
public Word[] wordList;
}
This would get translated in to JSON that looks similar to
{
"wordList": [
{
"key": "Hello!",
"value": "¡Hola!"
},
{
"key": "Goodbye",
"value": "Adiós"
}
]
}
Once you deserialize your Translation
object you can convert it in to a dictionary for faster lookups.
Translation items = JsonUtility.FromJson<Translation>(transFile.text);
Dictionary<string, string> transDict = items.wordList.ToDictionary(x=>x.key, y=>y.value);
By making key's the untranslated word it is easy to make a extension method that will look up in the dictionary the translated word but if it can't find one it will use the 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;
}
}
Which you could use like
[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;
}
}
You may want to try moving the dictionary code out of GameSmartTranslate
and put it in a singleton game object so the dictionary does not get re-built for every label that has this script.
Update:
You could also try using the json
[{
"key": "Hello!",
"value": "¡Hola!"
}, {
"key": "Goodbye",
"value": "Adiós"
}]
this would let you get rid of the Translation
class and your code would look like
Word[] items = JsonUtility.FromJson<Word[]>(transFile.text);
But I am pretty sure Unity 5.3 does not work directly on the array type, I have not tried with 5.4.
Upvotes: 3