Reading a nested JSON file with Unity on Android

问题: I'm trying to read this JSON file. If it looks messy, here is a Pastebin of the JSON. If the code looks messy, here is the Pastebin for that as well! (Ignore the return sta...

问题:

I'm trying to read this JSON file. If it looks messy, here is a Pastebin of the JSON. If the code looks messy, here is the Pastebin for that as well! (Ignore the return statement in the DeserializeQuestions() function). This works flawlessly when I test it in the editor, but it breaks when I test it on an Android device.

I get this error message that is as cryptic as the Voynich Manuscript:

enter image description here

{
  "Questions": {
    "0": [ "Are all of these questions temporary?", "Yes they are", "No", "No nr 2", "No nr 3" ],
    "1": [ "Roughly how tall is Mount Everest?", "8848 meters", "9343 meters", "8.322 km", "73000 mm" ],
    "2": [ "What are the worlds most populated countries?", "China, India and the US", "China, Russia and the US", "Russia, Brazil and the Soviet Union", "England, Russia and the US" ],
    "3": [ "What is the highest mountain top in Stord?", "Mehammarsåta", "Mennene", "Utslettefjellet", "Siggjo" ],
    "4": [ "What field did Stephen Hawking mainly study?", "Theoretical physics", "Relative physics", "Imaginary physics", "The gravity of your mom" ],
    "5": [ "What field did Stephen Hawking mainly study?", "Theoretical physics", "Relative physics", "Imaginary physics", "The gravity of your mom" ],
    "6": [ "What is Asgeir Asgeirson's favorite car manufacturar?", "Mercedes", "Ferrari", "Lamborghini", "
}

SPACE

using UnityEngine;
using System.IO;
using System.Collections.Generic;
using System;
using Newtonsoft.Json.Linq;

public class JsonFileWriter : MonoBehaviour
{
    public GameController gameController;
    public Settings settings;
    public List<Dictionary<string, string>> allQuestions = new List<Dictionary<string, string>>();
    public string path;
    public string pathGameData;

    public void Start()
    {

        path = "jar:file://" + Application.dataPath + "!/assets/data.json";
#if UNITY_EDITOR
        path = Path.Combine(Application.streamingAssetsPath, "data.json");
#endif
        pathGameData = Path.Combine(Application.persistentDataPath, "gameData.json");
        //List<JsonString> temp = new List<JsonString>();
        //temp.Add(new JsonString(new string[]{ "The question","The correct answer","Answer 1","Answer 2","Answer 3"}));
        //SerializeData();
        DeserializeQuestions();
    }

    public void SerializeGameData(GameData data)
    {
        System.DateTime epochStart = new System.DateTime(1970, 1, 1, 0, 0, 0, System.DateTimeKind.Utc);
        string cur_time = (int)(System.DateTime.UtcNow - epochStart).TotalSeconds + "";
        data.date = cur_time;
        if (!File.Exists(pathGameData))
        {
            File.WriteAllText(pathGameData, "");
        }
        string containerJson = File.ReadAllText(pathGameData);
        GameDataContainer container = new GameDataContainer();
        container.container = new List<GameData>();
        if(containerJson != "")
        {
            container = JsonUtility.FromJson<GameDataContainer>(containerJson);
        }
        container.container.Add(data);
        if(container.container.Count > settings.save_this_many_games)
        {
            int lowest = (int)(System.DateTime.UtcNow - epochStart).TotalSeconds;
            foreach(GameData s in container.container)
            {
                if(Int32.Parse(s.date) < lowest)
                {
                    lowest = Int32.Parse(s.date);
                }
            }
            for (int i = container.container.Count - 1; i >= 0; i--)
            {
                if(Int32.Parse(container.container[i].date) == lowest)
                {
                    container.container.Remove(container.container[i]);
                }
            }
        }
        containerJson = JsonUtility.ToJson(container);
        File.WriteAllText(pathGameData, containerJson);
    }

    public void DeserializeQuestions()
    {
        string json;

        if (Application.platform == RuntimePlatform.Android)
        {
            WWW reader = new WWW(path);
            while (!reader.isDone) { }

            json = reader.text;
        }

        json = File.ReadAllText(path);


        JObject jo = JObject.Parse(json);
        Dictionary<string, List<string>> values = jo.SelectToken("Questions", false).ToObject<Dictionary<string, List<string>>>();
        foreach(var kv in values)
        {
            Dictionary<string, string> temp = new Dictionary<string, string>();
            int i = 0;
            foreach(string s in kv.Value)
            {
                temp.Add(i + "", s);
                i++;
            }
            allQuestions.Add(temp);
        }
    }
}

[Serializable]
public class GameData
{
    public string date;
    public string questions;
    public List<string> playerScoresNames;
    public List<int> playerScoresScores;
    public List<string> playerStatesNames;
    public List<int> playerStatesStates;
}

[Serializable]
public class GameDataContainer
{
    public List<GameData> container;
}

SPACE

03-10 20:18:11.653: E/Unity(28401): JsonReaderException: Unexpected character encountered while parsing value: ?. Path '', line 0, position 0.
03-10 20:18:11.653: E/Unity(28401):   at Newtonsoft.Json.JsonTextReader.ParseValue () [0x00000] in <filename unknown>:0 
03-10 20:18:11.653: E/Unity(28401):   at Newtonsoft.Json.JsonTextReader.Read () [0x00000] in <filename unknown>:0 
03-10 20:18:11.653: E/Unity(28401):   at Newtonsoft.Json.Linq.JObject.Load (Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Linq.JsonLoadSettings settings) [0x00000] in <filename unknown>:0 
03-10 20:18:11.653: E/Unity(28401):   at Newtonsoft.Json.Linq.JObject.Parse (System.String json, Newtonsoft.Json.Linq.JsonLoadSettings settings) [0x00000] in <filename unknown>:0 
03-10 20:18:11.653: E/Unity(28401):   at Newtonsoft.Json.Linq.JObject.Parse (System.String json) [0x00000] in <filename unknown>:0 
03-10 20:18:11.653: E/Unity(28401):   at JsonFileWriter.DeserializeQuestions () [0x00000] in <filename unknown>:0 
03-10 20:18:11.653: E/Unity(28401):   at JsonFileWriter.Start () [0x00000] in <filename unknown>:0 
03-10 20:18:11.653: E/Unity(28401):  
03-10 20:18:11.653: E/Unity(28401): (Filename:  Line: -1)

回答1:

I do not know why, but when reading my JSON file using WWW, a mystery question mark was placed at the beginning of the string. This threw the JSON parser off. If you just remove the question mark, it works fine. I can guarantee that this is not the optimal way of doing it, but it works. What I'm doing here is just removing the first ASCII encoded byte.

public void DeserializeQuestions()
{
    if (Application.platform == RuntimePlatform.Android)
    {
        WWW reader = new WWW(path);
        while (!reader.isDone) { }

        json = reader.text;

        byte[] bytes = Encoding.ASCII.GetBytes(json);
        byte[] tempBytes = new byte[bytes.Length-1];
        for(var i = 1; i < bytes.Length; i++)
        {
            tempBytes[i - 1] = bytes[i];
        }
        string tempString = System.Text.Encoding.ASCII.GetString(tempBytes);
        json = tempString;
    }
    else
    {
        json = File.ReadAllText(path);
    }

    JObject jo = JObject.Parse(json);
    Dictionary<string, List<string>> values = jo.SelectToken("Questions", false).ToObject<Dictionary<string, List<string>>>();
    foreach(var kv in values)
    {
        Dictionary<string, string> temp = new Dictionary<string, string>();
        int i = 0;
        foreach(string s in kv.Value)
        {
            temp.Add(i + "", s);
            i++;
        }
        allQuestions.Add(temp);
    }
}
  • 发表于 2019-03-12 20:46
  • 阅读 ( 276 )
  • 分类:sof

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除