mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 09:07:52 +08:00
Rework logic of TypedListConverter to remove extra converter for bindables
This commit is contained in:
parent
6c8f4addb8
commit
cae5677605
@ -22,7 +22,7 @@ namespace osu.Game.Beatmaps.ControlPoints
|
||||
[JsonIgnore]
|
||||
public IBindableList<ControlPoint> ControlPoints => controlPoints;
|
||||
|
||||
[JsonConverter(typeof(BindableListConverter<ControlPoint>))]
|
||||
[JsonConverter(typeof(TypedListConverter<ControlPoint>))]
|
||||
[JsonProperty]
|
||||
private readonly BindableList<ControlPoint> controlPoints = new BindableList<ControlPoint>();
|
||||
|
||||
|
@ -1,114 +0,0 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
|
||||
namespace osu.Game.IO.Serialization.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// A type of <see cref="JsonConverter"/> that serializes an <see cref="IBindableList{T}"/> alongside
|
||||
/// a lookup table for the types contained. The lookup table is used in deserialization to
|
||||
/// reconstruct the objects with their original types.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of objects contained in the <see cref="IBindableList{T}"/> this attribute is attached to.</typeparam>
|
||||
public class BindableListConverter<T> : JsonConverter<IBindableList<T>>
|
||||
{
|
||||
private readonly bool requiresTypeVersion;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new <see cref="BindableListConverter{T}"/>.
|
||||
/// </summary>
|
||||
// ReSharper disable once UnusedMember.Global
|
||||
public BindableListConverter()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new <see cref="BindableListConverter{T}"/>.
|
||||
/// </summary>
|
||||
/// <param name="requiresTypeVersion">Whether the version of the type should be serialized.</param>
|
||||
// ReSharper disable once UnusedMember.Global (Used in Beatmap)
|
||||
public BindableListConverter(bool requiresTypeVersion)
|
||||
{
|
||||
this.requiresTypeVersion = requiresTypeVersion;
|
||||
}
|
||||
|
||||
public override IBindableList<T> ReadJson(JsonReader reader, Type objectType, IBindableList<T> existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
var list = new BindableList<T>();
|
||||
|
||||
var obj = JObject.Load(reader);
|
||||
|
||||
if (obj["$lookup_table"] == null)
|
||||
return list;
|
||||
|
||||
var lookupTable = serializer.Deserialize<List<string>>(obj["$lookup_table"].CreateReader());
|
||||
if (lookupTable == null)
|
||||
return list;
|
||||
|
||||
if (obj["$items"] == null)
|
||||
return list;
|
||||
|
||||
foreach (var tok in obj["$items"])
|
||||
{
|
||||
var itemReader = tok.CreateReader();
|
||||
|
||||
if (tok["$type"] == null)
|
||||
throw new JsonException("Expected $type token.");
|
||||
|
||||
string typeName = lookupTable[(int)tok["$type"]];
|
||||
var instance = (T)Activator.CreateInstance(Type.GetType(typeName).AsNonNull())!;
|
||||
serializer.Populate(itemReader, instance);
|
||||
|
||||
list.Add(instance);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, IBindableList<T> value, JsonSerializer serializer)
|
||||
{
|
||||
var lookupTable = new List<string>();
|
||||
var objects = new List<JObject>();
|
||||
|
||||
foreach (var item in value)
|
||||
{
|
||||
var type = item.GetType();
|
||||
var assemblyName = type.Assembly.GetName();
|
||||
|
||||
string typeString = $"{type.FullName}, {assemblyName.Name}";
|
||||
if (requiresTypeVersion)
|
||||
typeString += $", {assemblyName.Version}";
|
||||
|
||||
int typeId = lookupTable.IndexOf(typeString);
|
||||
|
||||
if (typeId == -1)
|
||||
{
|
||||
lookupTable.Add(typeString);
|
||||
typeId = lookupTable.Count - 1;
|
||||
}
|
||||
|
||||
var itemObject = JObject.FromObject(item, serializer);
|
||||
itemObject.AddFirst(new JProperty("$type", typeId));
|
||||
objects.Add(itemObject);
|
||||
}
|
||||
|
||||
writer.WriteStartObject();
|
||||
|
||||
writer.WritePropertyName("$lookup_table");
|
||||
serializer.Serialize(writer, lookupTable);
|
||||
|
||||
writer.WritePropertyName("$items");
|
||||
serializer.Serialize(writer, objects);
|
||||
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
}
|
||||
}
|
@ -7,17 +7,18 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
|
||||
namespace osu.Game.IO.Serialization.Converters
|
||||
{
|
||||
/// <summary>
|
||||
/// A type of <see cref="JsonConverter"/> that serializes an <see cref="IReadOnlyList{T}"/> alongside
|
||||
/// A type of <see cref="JsonConverter"/> that serializes a list alongside
|
||||
/// a lookup table for the types contained. The lookup table is used in deserialization to
|
||||
/// reconstruct the objects with their original types.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of objects contained in the <see cref="IReadOnlyList{T}"/> this attribute is attached to.</typeparam>
|
||||
public class TypedListConverter<T> : JsonConverter<IReadOnlyList<T>>
|
||||
/// <typeparam name="T">The type of objects contained in the list this attribute is attached to.</typeparam>
|
||||
public class TypedListConverter<T> : JsonConverter
|
||||
{
|
||||
private readonly bool requiresTypeVersion;
|
||||
|
||||
@ -39,10 +40,9 @@ namespace osu.Game.IO.Serialization.Converters
|
||||
this.requiresTypeVersion = requiresTypeVersion;
|
||||
}
|
||||
|
||||
public override IReadOnlyList<T> ReadJson(JsonReader reader, Type objectType, IReadOnlyList<T> existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
var list = new List<T>();
|
||||
|
||||
var obj = JObject.Load(reader);
|
||||
|
||||
if (obj["$lookup_table"] == null)
|
||||
@ -69,15 +69,25 @@ namespace osu.Game.IO.Serialization.Converters
|
||||
list.Add(instance);
|
||||
}
|
||||
|
||||
if (objectType == typeof(IBindableList<T>) || objectType == typeof(BindableList<T>))
|
||||
return new BindableList<T>(list);
|
||||
|
||||
if (objectType == typeof(IReadOnlyList<T>))
|
||||
return list.AsReadOnly();
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, IReadOnlyList<T> value, JsonSerializer serializer)
|
||||
public override bool CanConvert(Type objectType)
|
||||
=> objectType == typeof(IBindableList<T>) || objectType == typeof(BindableList<T>) || objectType == typeof(IReadOnlyList<T>) || objectType == typeof(List<T>);
|
||||
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||
{
|
||||
var enumerable = (IEnumerable<T>)value!;
|
||||
var lookupTable = new List<string>();
|
||||
var objects = new List<JObject>();
|
||||
|
||||
foreach (var item in value)
|
||||
foreach (var item in enumerable)
|
||||
{
|
||||
var type = item.GetType();
|
||||
var assemblyName = type.Assembly.GetName();
|
||||
|
Loading…
Reference in New Issue
Block a user