eorzea-votes/client/EorzeaVotes/Model/IQuestion.cs

85 lines
2.5 KiB
C#

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace EorzeaVotes.Model;
[JsonConverter(typeof(QuestionConverter))]
internal interface IQuestion {
/// <summary>
/// The question's unique ID.
/// </summary>
public Guid Id { get; init; }
/// <summary>
/// The date at which the question was published.
/// </summary>
public string Date { get; init; }
/// <summary>
/// If the question is currently the active question for voting.
/// </summary>
public bool Active { get; init; }
/// <summary>
/// The body text of the question.
/// </summary>
public string Text { get; init; }
/// <summary>
/// A list of possible answers to the question.
/// </summary>
public string[] Answers { get; init; }
/// <summary>
/// The name given by the person who suggested this question.
/// </summary>
public string? Suggester { get; init; }
}
internal class QuestionConverter : JsonConverter {
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) {
throw new NotImplementedException();
}
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) {
if (reader.TokenType == JsonToken.Null) {
return null;
}
// load as object
var obj = JObject.Load(reader);
// get the type key from the object
var typeToken = obj.GetValue("type");
if (typeToken == null) {
throw new Exception("missing type key");
}
// parse as a string
var type = typeToken.Value<string>();
// determine the type to deserialise
var actualType = type switch {
"basic" => typeof(BasicQuestion),
"full" => typeof(FullQuestion),
_ => throw new Exception("invalid question type"),
};
// resolve the contract and create a default question
var contract = serializer.ContractResolver.ResolveContract(actualType);
var question = existingValue ?? contract.DefaultCreator!();
// populate the default question
using var subReader = obj.CreateReader();
serializer.Populate(subReader, question);
return question;
}
public override bool CanConvert(Type objectType) {
return objectType == typeof(IQuestion)
|| objectType == typeof(BasicQuestion)
|| objectType == typeof(FullQuestion);
}
}