using System; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace StardewModdingAPI.Toolkit.Serialization.Converters { /// The base implementation for simplified converters which deserialize without overriding serialization. /// The type to deserialize. internal abstract class SimpleReadOnlyConverter : JsonConverter { /********* ** Accessors *********/ /// Whether this converter can write JSON. public override bool CanWrite => false; /********* ** Public methods *********/ /// Get whether this instance can convert the specified object type. /// The object type. public override bool CanConvert(Type objectType) { return objectType == typeof(T) || Nullable.GetUnderlyingType(objectType) == typeof(T); } /// Reads the JSON representation of the object. /// The JSON reader. /// The object type. /// The object being read. /// The calling serializer. public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { string path = reader.Path; switch (reader.TokenType) { case JsonToken.Null when Nullable.GetUnderlyingType(objectType) != null: return null; case JsonToken.StartObject: return this.ReadObject(JObject.Load(reader), path); case JsonToken.String: return this.ReadString(JToken.Load(reader).Value(), path); default: throw new SParseException($"Can't parse {typeof(T).Name} from {reader.TokenType} node (path: {reader.Path})."); } } /// Writes the JSON representation of the object. /// The JSON writer. /// The value. /// The calling serializer. public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { throw new InvalidOperationException("This converter does not write JSON."); } /********* ** Protected methods *********/ /// Read a JSON object. /// The JSON object to read. /// The path to the current JSON node. protected virtual T ReadObject(JObject obj, string path) { throw new SParseException($"Can't parse {typeof(T).Name} from object node (path: {path})."); } /// Read a JSON string. /// The JSON string value. /// The path to the current JSON node. protected virtual T ReadString(string str, string path) { throw new SParseException($"Can't parse {typeof(T).Name} from string node (path: {path})."); } } }