4
\$\begingroup\$

Like the title said the unity json utility does not seem to allow me to serialize the DateTime structure. Just to clarify the problem is that I'm serializing this class:

[Serializable]
public class SaveData {

public Vector3 playerPosition;
public Quaternion playerRot;
public List<Item> inventory;

public DateTime saveTime;

public int playerHealth;

public int strength;
public int attack;
public int defense;
public int agility;

}

When I actually write to the json file I get everything but the DateTime and no errors. This is the result:

{
"playerPosition": {
    "x": -142.27000427246095,
    "y": -7.000000476837158,
    "z": -112.80999755859375
},
"playerRot": {
    "x": 0.0,
    "y": 0.0,
    "z": 0.0,
    "w": 1.0
},
"inventory": [],
"playerHealth": 100,
"strength": 0,
"attack": 0,
"defense": 0,
"agility": 0
}

Is there a way around this?

A little update to this question so that I can show another way I've worked around this problem if the answer below isn't for you.

I was recently working on a similar problem and solved it by doing the follow:

I created a new class called "NewDateTime":

[System.Serializable]
public class NewDateTime {
public int second;
public int minute;
public int hour;

public int day;
public int month;
public int year;

public NewDateTime CreateNewDateTime(DateTime dateTime) {
    NewDateTime newDateTime = new NewDateTime();
    newDateTime.second = dateTime.Second;
    newDateTime.minute = dateTime.Minute;
    newDateTime.hour = dateTime.Hour;
    newDateTime.day = dateTime.Day;
    newDateTime.month = dateTime.Month;
    newDateTime.year = dateTime.Year;

    return newDateTime;
}

public override string ToString() {
    return day + "/" + month + "/" + year + " at " + hour + ":" + minute + ":" + second;
}}

and then for example when I want to save the date to json I would do something like the following:

saveDateTime = newDateTime.CreateNewDateTime(DateTime.Now)

it's a rather simple workaround but I thought it might help.

\$\endgroup\$
4
  • \$\begingroup\$ More details? How's it working now? What are you expecting it to do? \$\endgroup\$
    – House
    Feb 17, 2017 at 23:06
  • \$\begingroup\$ I wish to use it to save the time when the player saves the game. I have the same system working. Everything else within the class which is being serialized is saving to the Json file apart from the DateTime. \$\endgroup\$
    – Yatoniea
    Feb 17, 2017 at 23:21
  • \$\begingroup\$ Yeah. So it's just missing from the resulting JSON? There's no errors? Is the field public? Technical details please. \$\endgroup\$
    – House
    Feb 17, 2017 at 23:24
  • \$\begingroup\$ Oh, sorry yes it is just missing the resulting json and no errors whatsoever. \$\endgroup\$
    – Yatoniea
    Feb 17, 2017 at 23:25

3 Answers 3

8
\$\begingroup\$

The problem with JsonUtility, is that it doesn't save properties, just public fields and fields with the [SerializeField] attribute.

You can solve this with another class and some conversion magic, like so:



Json Serializable Class

[Serializable]
struct JsonDateTime {
    public long value;
    public static implicit operator DateTime(JsonDateTime jdt) {
        Debug.Log("Converted to time");
        return DateTime.FromFileTimeUtc(jdt.value);
    }
    public static implicit operator JsonDateTime(DateTime dt) {
        Debug.Log("Converted to JDT");
        JsonDateTime jdt = new JsonDateTime();
        jdt.value = dt.ToFileTimeUtc();
        return jdt;
    }
}



Usage example

var time = DateTime.Now;
print(time);
var json = JsonUtility.ToJson((JsonDateTime) time);
print(json);
DateTime timeFromJson = JsonUtility.FromJson<JsonDateTime>(json);
print(timeFromJson);



Output

Output from above code

\$\endgroup\$
0
0
\$\begingroup\$

I just faced the same problem and I fixed that by using Newtonsoft instead of JsonUtility as a converter.

here is an example

//here we will serialise or deserialize the data

public void SaveData
{

        List<Model> models = new List<Model>();
        //just adding some data
        models.Add(new Model { playerHealth = 10, saveTime = DateTime.Now, strength = 50 });

        //here pasing the data that are stoed on that variable into a json format
        string jsonText = Newtonsoft.Json.JsonConvert.SerializeObject(models);
        Debug.Log(jsonText);
}

//this is the model

public class Model
{
    public DateTime saveTime;

    public int playerHealth;

    public int strength;

}

here are result enter image description here

\$\endgroup\$
0
\$\begingroup\$

As it happens, I was just working on a telemetry example for my students, where I used this approach:

[SerializeField] long _timecode;
public DateTimeOffset time {
    get {
        return DateTimeOffset.FromUnixTimeMilliseconds(_timecode);
    }
    set {
        _timecode = value.ToUnixTimeMilliseconds();
    }
}

This way the serialized form is just a simple 64-bit integer, while consuming code can read/write it using the richer DateTimeOffset API. In my case, using the Unix time convention helped ensure I'd get consistent behaviour between my Unity game and a Node.js server.

Anytime I needed the current moment, I'd capture it as data.time = System.DateTimeOffset.UtcNow;

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .