因为游戏对象不能被序列化,所以我编写了一个保存游戏对象名称的类,以便它可以通过名称找到它.然而,我在反序列化过程中收到了这个错误,并且我不知道为什么.

JsonSerializationException:在JSON中指定的类型‘GameObtReferencer,SaveSystem,Version=0.0.0.0,区域性=Null,PublicKeyToken=NULL’与‘UnityEngine.GameObject,UnityEngine.CoreModule,Version=0.0.0.0,区域性=Null,PublicKeyToken=NULL’不兼容.Path‘wrappedSaveDatas.$values[4].savedObject.other.$type’,线338,位置55.

这是我的自定义转换器:

public class GameObjectFromReferenceConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{       return objectType == typeof(GameObjectReferencer);
}

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{        throw new Exception("GameObjectFromReferenceConverter should only be used when loading");
}


public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
    GameObjectReferencer goRef = (GameObjectReferencer)reader.Value;

    
    return ((GameObjectReferencer)goRef).GetGameObject();
}
}

这是我的Referencer类:

 public class GameObjectReferencer
{
public string targetGameObjectName;

public GameObjectReferencer(string gameObjectName)
{
    this.targetGameObjectName = gameObjectName;  
}

public GameObject GetGameObject()
{
    GameObject go = GameObject.Find(targetGameObjectName);
    if (go == null)
        throw new System.Exception("Can't find object with the name " + targetGameObjectName);
    return go;
}

public override string ToString()
{
    return "GameObjectReference of \"" + targetGameObjectName+ "\"";
}

public static GameObjectReferencer GenerateReference(GameObject gameObject)
{
    return new GameObjectReferencer(gameObject.name);
}

}

推荐答案

你的GameObjectReferencer就是DTO (data transfer object)的一个例子

数据传输对象(DTO)是在进程之间传输数据的对象.

由于序列化和反序列化需要具有一致的格式,这通常意味着您的DTO必须同时用于两者.因此,您的转换器应该如下所示:

public class GameObjectFromReferenceConverter : JsonConverter
{
    public override bool CanConvert(Type objectType) => 
        typeof(GameObject).IsAssignableFrom(objectType); 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) =>
        serializer.Serialize(writer, GameObjectReferencer.GenerateReference((GameObject)value));

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) =>
        serializer.Deserialize<GameObjectReferencer>(reader)?.GetGameObject();
}

// Serialization DTO class for GameObject and derived types.
class GameObjectReferencer
{
    public string targetGameObjectName { get; set; }

    public GameObjectReferencer(string targetGameObjectName) => this.targetGameObjectName = targetGameObjectName;

    public GameObject GetGameObject() =>
        GameObject.Find(targetGameObjectName) ?? throw new System.Exception("Can't find object with the name " + targetGameObjectName);

    public static GameObjectReferencer GenerateReference(GameObject gameObject) => new GameObjectReferencer(gameObject.name);

    public override string ToString() => "GameObjectReference of \"" + targetGameObjectName+ "\"";
}

您还必须在序列化和反序列化的设置中使用转换器,例如:

var settings = new JsonSerializerSettings
{
    Converters = { new GameObjectFromReferenceConverter() },
    // Other settings as required, e.g.:
    TypeNameHandling = TypeNameHandling.Auto,
};

备注:

  • 当使用转换器进行序列化时,转换器必须负责all aspects序列化和反序列化,包括$type元数据的序列化和反序列化.因此,转换器不一定能很好地处理Json.NET的TypeHandHandling setting.

  • 反序列化时,传递给JsonConverter.CanConvert(objectType)objectType将是要反序列化的对象的声明类型.由于任何GameObject引用的声明类型通常是GameObject或某个子类型,因此在CanConvert中,您需要判断该类型是否可从GameObject而不是GameObjectReferencer赋值.

    在序列化时,objectType将是被序列化的实际的、具体的类型,它也将是GameObject的某个子类型.

  • ReadJson()内,值JsonReader.Value将是当前JSON token的值.当当前令牌是JsonToken.StartObject(即,位于{令牌上)时,JsonReader.Value将是null.

  • 为了使Json.NET能够使用参数化构造函数成功地反序列化类型,构造函数参数名必须与属性名匹配(这里是targetGameObjectName).

  • 在使用TypeNameHandling时,请务必注意Newtonsoft docs:

    当您的应用程序从外部源反序列化JSON时,应谨慎使用TypeNameHandling.使用None以外的值反序列化传入类型时,应使用自定义SerializationBinder进行验证.

    有关这可能是必要的原因的讨论,请参见100.

  • 有关使用GUID而不是名称的类似转换器,请参见100.

here. biggest biggest biggest

Csharp相关问答推荐

获取Windows和Linux上的下载文件夹

Blazor:计算值或保留为默认值

需要深入了解NpgSQL DateTimeOffset处理

如何保持主摄像头视角保持一致?

无法解析数据库上下文的服务

Polly使用泛型重试和重试包装函数

System.Net.Http.HttpClient.SendAsync(request)在docker容器内的POST方法30秒后停止

StackExchange.Redis.RedisServerException:调用ITransaction.ExecuteAsync()时出现错误未知命令取消监视

C#和ASP.NET核心标识:提高GetUserAsync调用的性能

如何在NET 8最小API中自动记录TypedResults.Stream响应

如何将端点(或с匹配请求并判断其路径)添加到BCL?

如何在.NET AOT中为所有枚举启用JsonStringEnumConverter

如何在onNext之前等待订阅者完成?

我可以强制System.Text.Json.JsonSerializer以非递归方式工作吗?

如何解决System.StackOverflowException:抛出System.StackOverflowException类型的异常.&# 39;生成随机代码时发生异常?

无法使用直接URL通过PictureBox.ImageLocation加载图像

单位中快照的倾斜方向

我是否以错误的方式使用了异步延迟初始化?

如何查找Span;T&>是否包含相同顺序的其他Span<;T&>

异步等待,如何在Windows窗体中使用它们?