cfutils/CFUtils/Serialization/ManifestConverter.cs

77 lines
3.2 KiB
C#

using System.Collections.Generic;
using System.Reflection;
using System.Linq;
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
using CFUtils.Serialization.Modpack;
namespace CFUtils.Serialization
{
internal class ManifestConverter : JsonConverter<Manifest>
{
PropertyInfo[] manifestProperties;
Type manifestType;
public ManifestConverter()
{
manifestType = typeof(Manifest);
manifestProperties = manifestType.GetProperties();
}
public override Manifest Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
string[] propertyNames = new string[manifestProperties.Length];
for (int i = 0; i < propertyNames.Length; i++) propertyNames[i] = manifestProperties[i].Name;
Manifest result = new Manifest();
HashSet<string> pendingProperties = new HashSet<string>(propertyNames);
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndObject)
{
if (pendingProperties.Count != 0)
{
throw new JsonException("Manifest is missing data. Will not proceed.");
}
return result;
}
if (reader.TokenType == JsonTokenType.PropertyName)
{
string propertyName = reader.GetString() ?? throw new JsonException();
if (propertyNames.Contains(propertyName))
{
PropertyInfo property = manifestProperties[Array.IndexOf(propertyNames, propertyName)];
pendingProperties.Remove(propertyName);
property.SetValue(result, JsonSerializer.Deserialize(ref reader, property.PropertyType, options));
}
else if (Enum.GetNames(typeof(ManifestGames)).Contains(propertyName, StringComparer.CurrentCultureIgnoreCase))
{
Game game = JsonSerializer.Deserialize<Game>(ref reader);
game.gameType = Enum.Parse<ManifestGames>(propertyName, true);
result.game = game;
}
}
else
{
throw new JsonException();
}
}
throw new JsonException(); // Reached end of stream and did not find ending token.
}
public override void Write(Utf8JsonWriter writer, Manifest value, JsonSerializerOptions options)
{
writer.WriteStartObject();
writer.WritePropertyName(value.game.gameType.ToString().ToLower());
JsonSerializer.Serialize(writer, value.game, typeof(Game), options);
for (int i = 0; i < manifestProperties.Length; i++)
{
PropertyInfo property = manifestProperties[i];
writer.WritePropertyName(property.Name);
JsonSerializer.Serialize(writer, property.GetValue(value), property.PropertyType, options);
}
writer.WriteEndObject();
}
}
}