using System.Collections.Generic; using System.Reflection; using System.Linq; using System; using System.Text.Json; using System.Text.Json.Serialization; using MCCFMD.Serialization.Modpack; namespace MCCFMD.Serialization { public class ManifestConverter : JsonConverter { 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 pendingProperties = new HashSet(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(ref reader); game.gameType = Enum.Parse(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(); } } }