我正在使用JSON .NET为Unity3D游戏编写自定义序列化程序。我们可以有一些GameObject类型的字段,它是一个Unity3D内部类,它将引用游戏中的资源资源。我们需要能够仅通过其'GUID字符串序列化GameObject属性。使用此信息,我们可以利用Unity3D的AssetDatabase来检索资产并将其加载到属性中。
public class Blueprint {
public IList<IComponent> Components = new List<IComponent>();
}
public class UnityPrefabs : IComponent {
public GameObject ViewPrefab;
public GameObject ModelPrefab;
}
我用于使用JSON .NET序列化的方法:
public void Serialize(Blueprint blueprint) {
blueprintData = JsonConvert.SerializeObject(blueprint, Formatting.Indented,
new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.All,
Converters = new List<JsonConverter>() { new UnityPrefabConverter() },
//ContractResolver = new ConverterContractResolver()
});
}
public Blueprint Deserialize() {
var blueprint = string.IsNullOrEmpty(blueprintData)
? new Blueprint() : JsonConvert.DeserializeObject<Blueprint>(blueprintData,
new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.All,
//TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple,
NullValueHandling = NullValueHandling.Include,
Converters = new List<JsonConverter>() { new UnityPrefabConverter() },
});
return blueprint;
}
我确实尝试编写自定义转换器,但没有调用Write()方法,只有Read()是:
public class UnityPrefabConverter : JsonConverter {
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var go = value as GameObject;
var guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(go));
writer.WriteValue(guid);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
Debug.Log("Reading json");
if (existingValue == null) return null;
return AssetDatabase.LoadAssetAtPath<GameObject>(AssetDatabase.GUIDToAssetPath(existingValue as string));
}
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(GameObject));
}
}
我现在能找到的唯一奇怪的是它没有为GameObject字段序列化JSON中的类型:
{\r\n \"$type\": \"CubeBasic.Model.UnityPrefabs, Assembly-CSharp\",\r\n
\ \"ViewPrefab\": \"\",\r\n \"ModelPrefab\": null\r\n }\r\n
\ ]\r\n }\r\n}"
答案 0 :(得分:1)
您应该尝试使用Newtonsoft(可以将其作为Nuget包添加到项目中),然后编写一个通用的JSonSerializer类
using Newtonsoft.Json;
public class JSonSerializer : IObjectSerializer
{
public string ToJson<T>(T obj)
{
return JsonConvert.SerializeObject(obj);
}
public T FromJson<T>(string json)
{
try
{
return JsonConvert.DeserializeObject<T>(json);
}
catch(JsonReaderException e)
{
throw new ObjectSerializationException(e);
}
}
}
答案 1 :(得分:1)
您的转换器未被调用,因为在序列化期间,objectType
是被序列化的GameObject
的实际类型,因此是GameObject
的子类型。修改CanConvert
以使用Type.IsAssignableFrom(Type)
:
public override bool CanConvert(Type objectType)
{
return typeof(GameObject).IsAssignableFrom(objectType);
}
此外,在您的ReadJson
中,您可能不想检查existingValue
是否为空,而是您想要这样做:
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
Debug.Log("Reading json");
if (reader.TokenType == JsonToken.Null)
return null;
var guid = (string)JToken.Load(reader); // Load the GUID value
return AssetDatabase.LoadAssetAtPath<GameObject>(AssetDatabase.GUIDToAssetPath(guid));
}
existingValue
是对包含对象的构造函数中预先分配的POCO的引用。
由于您已为JsonConverter
编写了自己的GameObject
,因此除非您在转换器中明确这样做,否则不会写object types。但是,由于您实际上并未对对象进行反序列化,而只是从某个数据库中获取该对象,因此我认为没有必要。