- Home /
How to store int[][] as persistent data?
I have a question related to my recent other question here .
Basically what I'm trying to do is store coordinate data which holds values. Ideally I want to use a int[][]
because the coordinates will not always represent a square or rectangle but can be another 'jagged' shape.
Each coordinate holds data relevant to it, so like in an image where each [x,y] coordinate holds data about the color the pixel represent. But mine would be [x][y] and hold some int data like 1 or 0, etc;
So far I've tried using JavaScriptSerializer but I can't get past assembly errors (see the link above). I've also tried using JsonUtility.ToJson directly but I keep getting back {}
with nothing inside it.
here's how I set my code: (another gameObject's script calls Data.MakeFromDefaultData()
)
using System;
using UnityEngine;
using System.IO;
//using System.Web.Script.Serialization;
public class Data
{
//JavaScriptSerializer jss = new JavaScriptSerializer ();
public string MakeFromDefaultData (int x, int y)
{
var data = new IntData ();
data.makeCoordinates (x, y);
//string js = jss.Serialize (data);
string json = JsonUtility.ToJson (data); // string json = JsonUtility.ToJson (js);
StreamWriter writer = new StreamWriter ("Assets/Scripts/Data/data.json");
writer.Write (json);
writer.Close ();
StreamReader reader = new StreamReader ("Assets/Scripts/Data/data.json");
string jsonR = reader.ReadToEnd ();
reader.Close ();
return JsonUtility.FromJson<string> (jsonR);
}
}
[Serializable]
public class IntData
{
public int[][] coordinates;
public void makeCoordinates (int x, int y) {
coordinates = new int[x][];
for (int i = 0; i < x; i++) {
coordinates [i] = new int[y];
for (int j = 0; j < y; j++) {
coordinates [i] [j] = 1;
}
}
}
}
Any idea how I can read/write int[][]
data to json (or any other means?) and back?
Answer by $$anonymous$$ · Nov 23, 2017 at 06:12 AM
I found a solution for this using JsonHelper
class. Not sure who to give credit to as I've seen different people pass this around and take credit -
public class JsonHelper
{
//Usage:
//YouObject[] objects = JsonHelper.getJsonArray<YouObject> (jsonString);
public static T[] getJsonArray<T> (string json)
{
string newJson = "{ \"array\": " + json + "}";
Wrapper<T> wrapper = JsonUtility.FromJson<Wrapper<T>> (newJson);
return wrapper.array;
}
//Usage:
//string jsonString = JsonHelper.arrayToJson<YouObject>(objects);
public static string arrayToJson<T> (T[] array)
{
Wrapper<T> wrapper = new Wrapper<T> { array = array };
string piece = JsonUtility.ToJson (wrapper);
var pos = piece.IndexOf (":");
piece = piece.Substring (pos + 1); // cut away "{ \"array\":"
pos = piece.LastIndexOf ('}');
piece = piece.Substring (0, pos); // cut away "}" at the end
return piece;
}
[Serializable]
private class Wrapper<T>
{
public T[] array;
}
}
For My purpose I added an extra loop to make it a 2 dimensional array;
string json = "{ \"coordinates\": [ ";
for (int k = 0; k < data.coordinates.Length; k++) {
json += JsonHelper.arrayToJson (data.coordinates [k]);
if (k != data.coordinates.Length - 1) {
json += ",";
} else {
json += "]}";
}
}
Answer by JedBeryll · Nov 23, 2017 at 06:13 AM
If you want to use this within the assets folder you're much better off with a scriptable object. This only works if you do it in the editor as far as i know and wont work in a build.
The binary formatter can serialize most things. Haven't tried jagged arrays but it's not hard to set up and try. If you want to include these files in a build you can save to streaming assets path or if you do this on the end users machine, use persistent datapath.
public static class DataSerializer {
public static void Save(object obj, string fullPath) {
FileStream stream = new FileStream(fullPath, FileMode.Create, FileAccess.Write);
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, obj);
stream.Close();
}
public static T Load<T>(string fullPath) {
FileStream stream = new FileStream(fullPath, FileMode.Open, FileAccess.Read);
BinaryFormatter formatter = new BinaryFormatter();
object obj = formatter.Deserialize(stream);
stream.Close();
return (T) obj;
}
}
usage:
DoubleData doubleData = new DoubleData();
//...
//saving:
DataSerializer.Save(doubleData, "whatever/path/you/want.xyz");
//Loading:
DoubleData loaded = DataSerializer.Load<DoubleData>("whatever/path/you/want.xyz");
strange ti$$anonymous$$g! thanks for the help but I had just posted my own solution 1 $$anonymous$$ before this one. I'm not sure what you mean by your solution will work in the editor but not a build. Why is that? Would $$anonymous$$e have the same problem?
Yeah i just saw it. I'll leave my answer there in case someone else needs it. I meant that you can only create an asset in the editor which means you cannot save a scriptable object in a build. The serializer thing will work fine. Both solutions.
It is true that you can't create an "asset" at runtime. However you can use Unity's JsonUtility to save a ScriptableObject to JSON. However the main problem is that jagged arrays are not supported by Unity's serializer which includes the JsonUtility.
However as you said the BinaryFormatter does work
Your answer
Follow this Question
Related Questions
Scriptable objects become volatile on android 1 Answer
How do I go about using a server to store and retrieve data? 0 Answers
Component Is Heavy 2 Answers
Why PlayerPrefs not working although I use "HasKey" and Save() on android? 0 Answers
How easy it is to fake data stored in Application.persistentDataPath? 1 Answer