我正在开发一款名为UserInfo
的游戏。
在UserInfo
类内部,有一个public List<Lineup> lineups
变量。
并且Lineup
包含public Dictionary<Vector2Int, Collection> cardLocations
。
我的问题是,JsonConvert.SerializeObject
可以正确产生所需的结果,但是当我执行JsonConvert.DeserializeObject<UserInfo>
时,Vector2Int
仍然是像"(x, y)"
这样的字符串。
我该如何解决?
我写了一个JsonConverter
进行转换,并使用了
JsonConvert.SerializeObject(userInfo, Formatting.Indented, new Vec2Converter())
用于序列化和
JsonConvert.DeserializeObject<UserInfo>(json, new Vec2Converter())
反序列化,但这是行不通的。
这是我的
JsonConverter
脚本:using Newtonsoft.Json;
using UnityEngine;
using System;
public class Vec2Converter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(value.ToString());
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var vector2Int = serializer.Deserialize<Vector2Int>(reader);
Debug.Log(vector2Int);
return vector2Int;
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Vector2Int);
}
}
另一个奇怪的事情是,当我尝试将
Vector2Int
更改为其他数据结构(例如Lineup
或Dictionary<Vector2Int, Collection>
)时,单击播放时Unity退出。我改回来后,一切正常。好的表示它没有退出,但仍然给我错误消息。忘记输入错误消息:
ArgumentException: Could not cast or convert from System.String to UnityEngine.Vector2Int
这是课程。
public class UserInfo {
public string username;
public int playerID;
public List<Collection> collection = new List<Collection>();
public List<Lineup> lineups = new List<Lineup>(); // Here is the problem
public Dictionary<string, int> contracts = new Dictionary<string, int>();
public int coins = 0;
public int rank = 0;
public int lastLineupSelected = -1;
public int winsToday = 0;
public Stats total = new Stats();
public Dictionary<string, Stats> boardResults = new Dictionary<string, Stats>();
public List<Mission> missions;
public string preferredBoard = "Standard Board";
public string lastModeSelected = "";
public int gameID;
public bool missionSwitched = false;
}
public class Lineup
{
public Dictionary<Vector2Int, Collection> cardLocations; // Here is the problem
public List<Tactic> tactics;
public string boardName;
public string lineupName;
public string general;
public bool complete;
}
public class Collection
{
public string name = "";
public string type = "";
public int count = 1;
public int health = 0;
public int oreCost = 0;
}
最佳答案
从JsonConverter
派生的自定义序列化器需要做更多的工作,并且几乎没有错误。首先,请注意,您正在尝试对Dictionary
的Vector2Int
进行序列化/反序列化,而不仅仅是Vector2Int
变量。
是这样的:
public Dictionary<Vector2Int, Collection> cardLocations.
不
public Vector2Int cardLocations;
由于上述声明,您的
override bool CanConvert(Type objectType)
函数应检查typeof(Dictionary<Vector2Int, Collection>)
而不是typeof(Vector2Int)
。另外,您还需要添加检查以确定何时运行自定义反序列化器。序列化:
1.在序列化json的
WriteJson
函数中,您只需要自定义引发异常的Dictionary<Vector2Int, Collection>
部分,因此请确保自定义代码仅在类型为Dictionary<Vector2Int, Collection>
时运行。您可以通过将代码放入if (value is Dictionary<Vector2Int, Collection>)
中来实现。2.从第二个参数中获取字典进行序列化。调用
writer.WriteStartArray()
,以便将每个值写为数组。现在,遍历Dictionary
,用writer.WriteValue(key)
编写密钥,然后用serializer.Serialize(writer, entry.Value);
编写值。3.在循环调用
writer.WriteStartArray();
之后/之外,然后从该函数返回。如果#1中的
if (value is Dictionary<Vector2Int, Collection>)
是false
,则只需调用writer.WriteStartObject()
,然后再调用writer.WriteEndObject()
。反序列化:
4,确定何时运行自定义反序列化器
序列化时,我们在#1中使用
if (value is Dictionary<Vector2Int, Collection>)
来确定是否应运行自定义序列化程序代码,但对于反序列化,我们使用if (reader.TokenType == JsonToken.StartArray)
来确定是否已到达在ReadJson
中进行自定义序列化的数组部分功能。5.使用
JArray.Load(reader);
获取我们序列化的阵列数据。在返回的数组中,其中的第一个元素是Dictionary
中的键,第二个元素是Dictionary
中的值。第三个元素是Dictionary
中的第二个键。第四个元素是Dictionary
中的第二个值,依此类推。6.分隔
JArray
中的键和值。为了简化此过程,请按
JArray
而不是2
循环1
增量。通过增加2
,可以很容易地使用JArray[loop + 0]
检索密钥,并且可以使用JArray[loop + 1]
在相同的循环中检索值。for (int i = 0; i < jArray.Count; i += 2)
{
//Key
string key = jArray[i + 0].ToString();
//Value
string value = jArray[i + 1].ToString();
}
7.以
Vector2Int
格式获取密钥。只需使用
Vector2Int
将密钥从#6反序列化为JsonConvert.DeserializeObject<Vector2Int>(key)
。8.以
Collection
格式获取值。只需使用
Collection
将#6中的值反序列化为JsonConvert.DeserializeObject<Collection>(value)
。9,重建数据
创建
Dictionary<Vector2Int, Collection>
的新实例,然后将#7中的键和#8中的值添加到它,然后从ReadJson
函数返回它。如果#4中的
if (reader.TokenType == JsonToken.StartArray)
是false
,只需从Dictionary<Vector2Int, Collection>
函数创建并返回ReadJson
的新实例,而无需向其添加键或值。class Vec2DictionaryConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(Dictionary<Vector2Int, Collection>).IsAssignableFrom(objectType);
}
//Deserialize json to an Object
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
//Debug.Log("De-serializing!");
if (reader.TokenType == JsonToken.StartArray)
{
// Load JArray from stream
JArray jArray = JArray.Load(reader);
//Where to re-create the json data into
Dictionary<Vector2Int, Collection> dict = new Dictionary<Vector2Int, Collection>();
if (jArray == null || jArray.Count < 2)
{
return dict;
}
//Do the loop faster with +=2
for (int i = 0; i < jArray.Count; i += 2)
{
//first item = key
string firstData = jArray[i + 0].ToString();
//second item = value
string secondData = jArray[i + 1].ToString();
//Create Vector2Int key data
Vector2Int vect = JsonConvert.DeserializeObject<Vector2Int>(firstData);
//Create Collection value data
Collection values = JsonConvert.DeserializeObject<Collection>(secondData);
//Add both Key and Value to the Dictionary if key doesnt exit yet
if (!dict.ContainsKey(vect))
dict.Add(vect, values);
}
//Return the Dictionary result
return dict;
}
return new Dictionary<Vector2Int, Collection>();
}
//SerializeObject to Json
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
//Debug.Log("Serializing!");
if (value is Dictionary<Vector2Int, Collection>)
{
//Get the Data to serialize
Dictionary<Vector2Int, Collection> dict = (Dictionary<Vector2Int, Collection>)value;
//Loop over the Dictionary array and write each one
writer.WriteStartArray();
foreach (KeyValuePair<Vector2Int, Collection> entry in dict)
{
//Write Key (Vector)
serializer.Serialize(writer, entry.Key);
//Write Value (Collection)
serializer.Serialize(writer, entry.Value);
}
writer.WriteEndArray();
return;
}
writer.WriteStartObject();
writer.WriteEndObject();
}
}
用法:
连载
string json = JsonConvert.SerializeObject(userInfo, new Vec2DictionaryConverter());
反序列化
UserInfo obj = JsonConvert.DeserializeObject<UserInfo>(json, new Vec2DictionaryConverter());