Unity Json.net bson Самостоятельная ссылка - PullRequest
1 голос
/ 31 октября 2019

Я пытаюсь сохранить контент в моей игре на Json.net. с помощью этого ресурса я сохранил свою игру в формате JSON, но теперь я хочу сохранить ее в формате Bson, поскольку не хочу, чтобы мои игроки могли легко редактировать файлы сохранения.

Вот код работает и сохраняет мои игровые данные в json.

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

Здесь я пытаюсь сохранить свои игровые данные в формате bson, но я не совсем знаю, как отключить ReferenceLoopHandlingв формате bson.

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]'.

1 Ответ

1 голос
/ 31 октября 2019

Вы можете использовать фабричные методы 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 была перемещена в собственный пакет Newtonsoft.Json.Bson в Json.NET 10.0.1. В этой версии или позже вы должны использовать BsonDataWriterBsonDataReader), так как BsonWriter устарел и в конечном итоге будет удален.

  • serializer.ToString() не собирается возвращать сериализованный BSON;вместо этого используйте MemoryStream.ToArray(), то есть

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

    Однако более эффективно выполнять потоковую передачу непосредственно в файл, как показано в методах расширения выше.

  • serializer.ReferenceLoopHandling.Equals(false); - неправильный способ установить свойство ReferenceLoopHandling в c #. Вместо этого установите его так, как если бы это было поле:

     serializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
    

    См .: Использование свойств (Руководство по программированию в C #) .

Демонстрационная скрипка здесь .

...