using System; using System.Reflection; using System.Text.Json; namespace InABox.Core { public class CoreTableJsonConverter : CustomJsonConverter { public override void Write(Utf8JsonWriter writer, CoreTable value, JsonSerializerOptions options) { if (value == null) { writer.WriteNullValue(); return; } writer.WriteStartObject(); // Columns writer.WritePropertyName("Columns"); writer.WriteStartObject(); foreach (var column in value.Columns) writer.WriteString(column.ColumnName, column.DataType.EntityName()); writer.WriteEndObject(); // Rows writer.WritePropertyName("Rows"); writer.WriteStartArray(); foreach (var row in value.Rows) { writer.WriteStartArray(); foreach (var column in value.Columns) { WriteJson(writer, row[column.ColumnName]); } writer.WriteEndArray(); } writer.WriteEndArray(); writer.WriteEndObject(); } public override CoreTable? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.Null) return null; var result = new CoreTable(); try { reader.Read(); while(reader.TokenType != JsonTokenType.EndObject) { if (reader.TokenType == JsonTokenType.PropertyName) { var propertyName = reader.GetString(); reader.Read(); // Move to property value if (propertyName == "Columns") { if(reader.TokenType != JsonTokenType.StartObject) { throw new SerialisationException($"Unexpected token type after \"Columns\": {reader.TokenType}"); } reader.Read(); // Skip over StartObject while (reader.TokenType != JsonTokenType.EndObject) { string name = reader.GetString()!; reader.Read(); // Advance to the property value var type = reader.GetString(); result.Columns.Add(new CoreColumn { ColumnName = name, DataType = CoreUtils.GetEntity(type ?? "") }); reader.Read(); // Move to next token } reader.Read(); // Skip EndObject } else if (propertyName == "Rows") { if(reader.TokenType != JsonTokenType.StartArray) { throw new SerialisationException($"Unexpected token type after \"Rows\": {reader.TokenType}"); } reader.Read(); // Skip StartArray while (reader.TokenType != JsonTokenType.EndArray) { if(reader.TokenType != JsonTokenType.StartArray) { throw new SerialisationException($"Unexpected token type: {reader.TokenType}"); } reader.Read(); // Skip StartArray var iCol = 0; var newrow = result.NewRow(); while (reader.TokenType != JsonTokenType.EndArray) { var col = result.Columns[iCol]; newrow[col.ColumnName] = CoreUtils.ChangeType(ReadJson(reader), col.DataType); reader.Read(); iCol++; } result.Rows.Add(newrow); reader.Read(); // Skip EndArray } reader.Read(); // Skip EndArray } } } } catch(SerialisationException e) { Logger.Send(LogType.Error, "", $"SerialisationException: {e.Message}"); return null; } catch (Exception e) { Logger.Send(LogType.Error, "", string.Format("*** Unknown Error: {0}\n{1}", e.Message, e.StackTrace)); } return result; } public override bool CanConvert(Type objectType) { return typeof(CoreTable).IsAssignableFrom(objectType); } } }