Reputation: 943
I have a class:
using System;
[Serializable]
public class GameMessage
{
public string cmd;
public object data;
public string seedId;
public string peerId;
public GameMessage( string cmd, object data, string seedId = null, string peerId = null )
{
this.cmd = cmd;
this.data = data;
this.seedId = seedId;
this.peerId = peerId;
}
}
And in some place at the code I calling:
JsonUtility.ToJson(new GameMessage("chat/say", "hello!"));
After this operation, I don't have data property in result JSON.
The result is: {"cmd":"chat/say","seedId":"","peerId":""}
What's wrong? Why data doesn't appear in final JSON structure.
data
has any type. (possible string, custom object, float, array, etc...)
EDIT: I'm looking for some workaround solution for my data with serialization and deserialization because JsonUtility
doesn't support all primitive data types as root for data and require only to parse UnityEngine.Object
object.
Upvotes: 1
Views: 1284
Reputation: 10721
So JSONUtility does not support object serialization. Makes sense when you think that an object type reference is just a four bytes address with no knowledge of the actual size of the object. So the serializer has no way to know what is the data to serialize.
You can turn your byte [] into a string64. That string can be serialized by the JsonUtility. Here is how your class would look:
[Serializable]
public class GameMessage
{
public string cmd;
public string data;
public string seedId;
public string peerId;
public byte [] Data{ get { return Encoding.ASCII.GetBytes(this.data); } }
public GameMessage( string cmd, byte[] data, string seedId = null, string peerId = null )
{
this.cmd = cmd;
this.data = Convert.BaseToString64(data);
this.seedId = seedId;
this.peerId = peerId;
}
}
Here is how you use the class ctor, considering any type can be the data, you can use this method (Convert any object to a byte[]):
byte[] ObjectToByteArray(object obj)
byte[] ObjectToByteArray(object obj)
{
if(obj == null)
return null;
BinaryFormatter bf = new BinaryFormatter();
using (MemoryStream ms = new MemoryStream())
{
bf.Serialize(ms, obj);
return ms.ToArray();
}
}
object ByteArrayToObject(byte[] buffer)
{
MemoryStream ms = new MemoryStream (buffer);
BinaryFormatter bf = new BinaryFormatter ();
return bf.Deserialize (ms);
}
Now let's say you have a float of value 5.12f
float f = 5.12f;
GameMessage gm = new GameMessage("chat/say", ObjectToByteArray((object)f));
string json = JsonUtility.ToJson(gm);
Now you want to retrieve it:
var gm = JsonUtility.FromJson<GameMessage> (json);
byte[] array = gm.Data;
object f = ByteArrayToObject (array);
Debug.Log (f);
The return item is of type object. If you need to know its type (since you said it can be any type, you may want to know what it was before serialization), just use:
f.GetType();
this will tell you what it actually is. There is no straightforward way to cast using a Type reference. You'd have to go through reflection or dynamic.
C# is a strongly typed language (as opposed to languages like Javascript or Php where you can somehow switch type of a variable). For this reason, when you end up like in your situation, where any given type is welcome, this is no good design and will lead to issues or huge code, hard to maintain. You should probably restrict the possibilities.
Upvotes: 1