From 0122abaf203c1efa70e5e48336cc4800d4f01cc0 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 16 Jan 2018 19:16:58 -0500 Subject: add JSON converters for crossplatform-incompatible types (#423) --- .../Framework/Serialisation/RectangleConverter.cs | 84 ++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/SMAPI/Framework/Serialisation/RectangleConverter.cs (limited to 'src/SMAPI/Framework/Serialisation/RectangleConverter.cs') diff --git a/src/SMAPI/Framework/Serialisation/RectangleConverter.cs b/src/SMAPI/Framework/Serialisation/RectangleConverter.cs new file mode 100644 index 00000000..74df54e2 --- /dev/null +++ b/src/SMAPI/Framework/Serialisation/RectangleConverter.cs @@ -0,0 +1,84 @@ +using System; +using System.Text.RegularExpressions; +using Microsoft.Xna.Framework; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using StardewModdingAPI.Framework.Exceptions; + +namespace StardewModdingAPI.Framework.Serialisation +{ + /// Handles deserialisation of for crossplatform compatibility. + internal class RectangleConverter : 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(Rectangle); + } + + /// 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) + { + // Linux/Mac: { "X": 1, "Y": 2, "Width": 3, "Height": 4 } + // Windows: "{X:1 Y:2 Width:3 Height:4}" + JToken token = JToken.Load(reader); + switch (token.Type) + { + case JTokenType.Object: + { + JObject obj = (JObject)token; + int x = obj.Value(nameof(Rectangle.X)); + int y = obj.Value(nameof(Rectangle.Y)); + int width = obj.Value(nameof(Rectangle.Width)); + int height = obj.Value(nameof(Rectangle.Height)); + return new Rectangle(x, y, width, height); + } + + case JTokenType.String: + { + string str = token.Value(); + if (string.IsNullOrWhiteSpace(str)) + return Rectangle.Empty; + + var match = Regex.Match(str, @"^\{X:(?\d+) Y:(?\d+) Width:(?\d+) Height:(?\d+)\}$"); + if (!match.Success) + throw new SParseException($"Can't parse {typeof(Rectangle).Name} from {reader.Path}, invalid string format."); + + int x = Convert.ToInt32(match.Groups["x"].Value); + int y = Convert.ToInt32(match.Groups["y"].Value); + int width = Convert.ToInt32(match.Groups["width"].Value); + int height = Convert.ToInt32(match.Groups["height"].Value); + + return new Rectangle(x, y, width, height); + } + + default: + throw new SParseException($"Can't parse {typeof(Rectangle).Name} from {reader.Path}, must be an object or string."); + } + } + + /// 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."); + } + } +} -- cgit