Unity Json.net bson自参考循环



我正试图用Json.net保存游戏中的内容。使用此资源,我将游戏保存到Json,但现在我想将其保存为Bson格式,因为我不希望我的玩家能够轻松编辑保存文件。

这是代码的工作原理,并将我的游戏数据保存到json中。

File.WriteAllText(path, JsonConvert.SerializeObject(objectToSave, Formatting.Indented,
new JsonSerializerSettings
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
}));

在这里,我试图将我的游戏数据保存为bson格式,但我不太知道如何关闭bson格式的ReferenceLoopHandling。

using (var stream = new MemoryStream())
{
var serializer = new JsonSerializer();
var writer = new BsonWriter(stream);
serializer.ReferenceLoopHandling.Equals(false);
serializer.Serialize(writer, objectToSave);
File.WriteAllText(path, serializer.ToString());
}

当我运行此代码时,我会得到以下错误。

JsonSerializationException: Self referencing loop detected for property 'graph' with type 'StoryGraph'. Path 'nodes[0]'.

您可以使用工厂方法JsonSerializer.CreateDefault(JsonSerializerSettings)JsonSerializer.Create(JsonSerializerSettings)来制造具有所需设置的序列化程序,然后使用以下扩展方法直接序列化到文件:

public static partial class BsonExtensions
{
// In Json.NET 10.0.1 and later use https://www.nuget.org/packages/Newtonsoft.Json.Bson
public static void SerializeToFile<T>(T obj, string path, JsonSerializerSettings settings = null)
{
using (var stream = new FileStream(path, FileMode.Create))
using (var writer = new BsonWriter(stream)) // BsonDataWriter in Json.NET 10.0.1 and later
{
JsonSerializer.CreateDefault(settings).Serialize(writer, obj);
}
}
public static T DeserializeFromFile<T>(string path, JsonSerializerSettings settings = null)
{
using (var stream = new FileStream(path, FileMode.Open))
using (var reader = new BsonReader(stream)) // BsonDataReader in Json.NET 10.0.1 and later
{
var serializer = JsonSerializer.CreateDefault(settings);
//https://www.newtonsoft.com/json/help/html/DeserializeFromBsonCollection.htm
if (serializer.ContractResolver.ResolveContract(typeof(T)) is JsonArrayContract)
reader.ReadRootValueAsArray = true;
return serializer.Deserialize<T>(reader);
}
}
}

然后序列化如下:

BsonExtensions.SerializeToFile(objectToSave, path, 
new JsonSerializerSettings 
{ 
ReferenceLoopHandling = ReferenceLoopHandling.Ignore 
});

注:

  • 反序列化时请确保使用相同的设置。

  • BSON支持已转移到Json.NET10.0.1中自己的包Newtonsoft.Json.Bson中。在此版本或更高版本中,您应该使用BsonDataWriter(和BsonDataReader(,因为BsonWriter已过时,并且最终将被删除。

  • serializer.ToString()不会返回已序列化的BSON;而是使用MemoryStream.ToArray(),即

    File.WriteAllBytes(path, stream.ToArray());
    

    但是,如上面的扩展方法所示,直接流式传输到文件更有效。

  • serializer.ReferenceLoopHandling.Equals(false);不是在c#中设置ReferenceLoopHandling属性的正确方法。相反,将其设置为一个字段:

    serializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
    

    请参阅:使用属性(C#编程指南(。

在这里演示小提琴。

您也可以直接设置序列化程序:

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
// Fix: Ignore loops
serializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
...

这为我解决了Unity C#上下文中的问题。

最新更新