2017-03-20 3 views
1

GameObjectを内部で別のもの(GameObjectMetadata)にシリアル化する必要がある状況があります。このデータには、後でデシリアライズするのに役立ちます。クラスのJSONシリアル化を別のクラスにリダイレクトする方法はありますか?

public struct GameObjectMetadata 
{ 
    public string AssetFullPath; 
    public string AssetBundle; 
    public string GUID; 
    public string UnityType; 
} 

public struct TestPrefabLink 
{ 
    public GameObject Prefab; 
} 

これを実現するために必要なJSON.NETコンバータを実装するのは本当に苦労しています。私はそれをしばらくして、以下のコードを思いついた。また、主に動作しますが、私は次のエラーを取得する:私がここでやっているいくつかの悪いJSONを引き起こしているものは何でもそうです

public class GameObjectMetadataJsonConverter : JsonConverter 
{ 
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    {  
     var jobj = JObject.FromObject(value); 
     jobj.WriteTo(writer); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     var metadata = serializer.Deserialize<GameObjectMetadata>(reader); 

     // Snipped - Code here successfully converts to GameObject 
    } 

    public override bool CanConvert(Type objectType) 
    { 
     return objectType == typeof (GameObjectMetadata); 
    } 
} 

public class UnityObjectJsonConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return typeof(UnityEngine.Object).IsAssignableFrom(objectType); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     return existingValue; // This should not be called. But it is?? 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     var metadata = new GameObjectMetadata(); 
     metadata.UnityType = value.GetType().ToString(); 

     var path = UnityEditor.AssetDatabase.GetAssetPath((UnityEngine.Object)value); 
     var bundleName = UnityEditor.AssetImporter.GetAtPath(path).assetBundleName; 
     var guid = UnityEditor.AssetDatabase.AssetPathToGUID(path); 

     metadata.AssetBundle = bundleName; 
     metadata.AssetFullPath = path; 
     metadata.GUID = guid; 

     //var jobj = JObject.FromObject(metadata); 
     //jobj.WriteTo(writer); 
     serializer.Serialize(writer, metadata); 
    } 
} 

JsonSerializationException: Unexpected token while deserializing object: EndObject. Path 'Components.$values[0]', line 14, position 7. Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) (at C:/Development/Releases/Json/Working/Newtonsoft.Json/Working-Signed/Src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs:336)

シリアライザ:使用

data = JsonConvert.SerializeObject(blueprint, Formatting.Indented, 
      new JsonSerializerSettings() 
      { 
       TypeNameHandling = TypeNameHandling.All, 
       NullValueHandling = NullValueHandling.Include, 
       ReferenceLoopHandling = ReferenceLoopHandling.Ignore, 
       Converters = new List<JsonConverter>() { new GameObjectMetadataJsonConverter(), new UnityObjectJsonConverter() } 
      }); 

コンバータ書き出す。しかし、私は他の構造体/クラスを期待されるものからどのように書き出すべきかを理解することはできません。直列化復元の際に、CanConvert(objectType)はないファイルにシリアル実際の型を直列化復元することが期待タイプと呼ばれる、ので

答えて

1

UnityObjectJsonConverter.ReadJson()は確かに呼び出されます。予想されるタイプはUnityEngine.Objectのサブタイプになります。 GameObjectMetadataJsonConverterのための必要はありません

public struct GameObjectMetadata 
{ 
    public GameObjectMetadata(UnityEngine.Object value) 
    { 
     if (value == null) 
      throw new ArgumentNullException(); 

     this.UnityType = value.GetType(); 

     var path = UnityEditor.AssetDatabase.GetAssetPath(value); 
     var bundleName = UnityEditor.AssetImporter.GetAtPath(path).assetBundleName; 
     var guid = UnityEditor.AssetDatabase.AssetPathToGUID(path); 

     this.AssetBundle = bundleName; 
     this.AssetFullPath = path; 
     this.GUID = guid; 
    } 

    public UnityEngine.Object GetRealObject() 
    { 
     // I'm not a unity3d developer so I am not sure this is the correct method to call. 
     return UnityEditor.AssetDatabase.LoadAssetAtPath(AssetFullPath, UnityType); 
    } 

    public string AssetFullPath; 
    public string AssetBundle; 
    public string GUID; 
    public Type UnityType; 
} 

public class UnityObjectJsonConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return typeof(UnityEngine.Object).IsAssignableFrom(objectType); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (reader.TokenType == JsonToken.Null) 
      return null; 
     var metadata = serializer.Deserialize<GameObjectMetadata>(reader); 
     return metadata.GetRealObject(); 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     // WriteJson is never called when value == null. Instead Json.NET calls writer.WriteNull() directly. 
     var metadata = new GameObjectMetadata((UnityEngine.Object)value); 
     serializer.Serialize(writer, metadata); 
    } 
} 

は、このようにあなたのような何かをする必要があります。

注意私はの開発者ではありません。したがって、AssetDatabase.LoadAssetAtPath(AssetFullPath, Type.GetType(UnityType))は、ゲームオブジェクトをそのメタデータから再構築するための正しい方法です。正しいもので置き換えてください。

+0

ロックソリッド!ありがとう、たくさんの仲間。 GetRealObject();のUnity APIでの推測に非常に近い) –

関連する問題