diff options
7 files changed, 35 insertions, 18 deletions
diff --git a/docs/release-notes.md b/docs/release-notes.md index 2840798d..f2dde81d 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -14,6 +14,7 @@ * Fixed deadlock in rare cases when injecting a file with an asset loader. * Fixed unhelpful error when a mod exposes a non-public API. * Fixed input events being raised for keyboard buttons when a textbox is receiving input. + * Fixed some JSON field names being case-sensitive. * For SMAPI developers: * Overhauled mod DB format to be more concise, reduce the memory footprint, and support versioning/defaulting more fields. diff --git a/src/SMAPI/Framework/InternalExtensions.cs b/src/SMAPI/Framework/InternalExtensions.cs index 71489627..ce67ae18 100644 --- a/src/SMAPI/Framework/InternalExtensions.cs +++ b/src/SMAPI/Framework/InternalExtensions.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using Microsoft.Xna.Framework.Graphics; +using Newtonsoft.Json.Linq; using StardewModdingAPI.Framework.Reflection; using StardewValley; @@ -148,5 +149,20 @@ namespace StardewModdingAPI.Framework // get result return reflection.GetField<bool>(Game1.spriteBatch, fieldName).GetValue(); } + + /**** + ** Json.NET + ****/ + /// <summary>Get a JSON field value from a case-insensitive field name. This will check for an exact match first, then search without case sensitivity.</summary> + /// <typeparam name="T">The value type.</typeparam> + /// <param name="obj">The JSON object to search.</param> + /// <param name="fieldName">The field name.</param> + public static T ValueIgnoreCase<T>(this JObject obj, string fieldName) + { + JToken token = obj.GetValue(fieldName, StringComparison.InvariantCultureIgnoreCase); + return token != null + ? token.Value<T>() + : default(T); + } } } diff --git a/src/SMAPI/Framework/Serialisation/CrossplatformConverters/ColorConverter.cs b/src/SMAPI/Framework/Serialisation/CrossplatformConverters/ColorConverter.cs index f4a2a26e..f1b2f04f 100644 --- a/src/SMAPI/Framework/Serialisation/CrossplatformConverters/ColorConverter.cs +++ b/src/SMAPI/Framework/Serialisation/CrossplatformConverters/ColorConverter.cs @@ -20,10 +20,10 @@ namespace StardewModdingAPI.Framework.Serialisation.CrossplatformConverters /// <param name="path">The path to the current JSON node.</param> protected override Color ReadObject(JObject obj, string path) { - int r = obj.Value<int>(nameof(Color.R)); - int g = obj.Value<int>(nameof(Color.G)); - int b = obj.Value<int>(nameof(Color.B)); - int a = obj.Value<int>(nameof(Color.A)); + int r = obj.ValueIgnoreCase<int>(nameof(Color.R)); + int g = obj.ValueIgnoreCase<int>(nameof(Color.G)); + int b = obj.ValueIgnoreCase<int>(nameof(Color.B)); + int a = obj.ValueIgnoreCase<int>(nameof(Color.A)); return new Color(r, g, b, a); } diff --git a/src/SMAPI/Framework/Serialisation/CrossplatformConverters/PointConverter.cs b/src/SMAPI/Framework/Serialisation/CrossplatformConverters/PointConverter.cs index 84c70989..434b7ea5 100644 --- a/src/SMAPI/Framework/Serialisation/CrossplatformConverters/PointConverter.cs +++ b/src/SMAPI/Framework/Serialisation/CrossplatformConverters/PointConverter.cs @@ -20,8 +20,8 @@ namespace StardewModdingAPI.Framework.Serialisation.CrossplatformConverters /// <param name="path">The path to the current JSON node.</param> protected override Point ReadObject(JObject obj, string path) { - int x = obj.Value<int>(nameof(Point.X)); - int y = obj.Value<int>(nameof(Point.Y)); + int x = obj.ValueIgnoreCase<int>(nameof(Point.X)); + int y = obj.ValueIgnoreCase<int>(nameof(Point.Y)); return new Point(x, y); } diff --git a/src/SMAPI/Framework/Serialisation/CrossplatformConverters/RectangleConverter.cs b/src/SMAPI/Framework/Serialisation/CrossplatformConverters/RectangleConverter.cs index b89551e3..62bc8637 100644 --- a/src/SMAPI/Framework/Serialisation/CrossplatformConverters/RectangleConverter.cs +++ b/src/SMAPI/Framework/Serialisation/CrossplatformConverters/RectangleConverter.cs @@ -21,10 +21,10 @@ namespace StardewModdingAPI.Framework.Serialisation.CrossplatformConverters /// <param name="path">The path to the current JSON node.</param> protected override Rectangle ReadObject(JObject obj, string path) { - int x = obj.Value<int>(nameof(Rectangle.X)); - int y = obj.Value<int>(nameof(Rectangle.Y)); - int width = obj.Value<int>(nameof(Rectangle.Width)); - int height = obj.Value<int>(nameof(Rectangle.Height)); + int x = obj.ValueIgnoreCase<int>(nameof(Rectangle.X)); + int y = obj.ValueIgnoreCase<int>(nameof(Rectangle.Y)); + int width = obj.ValueIgnoreCase<int>(nameof(Rectangle.Width)); + int height = obj.ValueIgnoreCase<int>(nameof(Rectangle.Height)); return new Rectangle(x, y, width, height); } @@ -36,7 +36,7 @@ namespace StardewModdingAPI.Framework.Serialisation.CrossplatformConverters if (string.IsNullOrWhiteSpace(str)) return Rectangle.Empty; - var match = Regex.Match(str, @"^\{X:(?<x>\d+) Y:(?<y>\d+) Width:(?<width>\d+) Height:(?<height>\d+)\}$"); + var match = Regex.Match(str, @"^\{X:(?<x>\d+) Y:(?<y>\d+) Width:(?<width>\d+) Height:(?<height>\d+)\}$", RegexOptions.IgnoreCase); if (!match.Success) throw new SParseException($"Can't parse {typeof(Rectangle).Name} from invalid value '{str}' (path: {path})."); diff --git a/src/SMAPI/Framework/Serialisation/SmapiConverters/ManifestDependencyArrayConverter.cs b/src/SMAPI/Framework/Serialisation/SmapiConverters/ManifestDependencyArrayConverter.cs index 6352e367..4150d5fb 100644 --- a/src/SMAPI/Framework/Serialisation/SmapiConverters/ManifestDependencyArrayConverter.cs +++ b/src/SMAPI/Framework/Serialisation/SmapiConverters/ManifestDependencyArrayConverter.cs @@ -40,9 +40,9 @@ namespace StardewModdingAPI.Framework.Serialisation.SmapiConverters List<IManifestDependency> result = new List<IManifestDependency>(); foreach (JObject obj in JArray.Load(reader).Children<JObject>()) { - string uniqueID = obj.Value<string>(nameof(IManifestDependency.UniqueID)); - string minVersion = obj.Value<string>(nameof(IManifestDependency.MinimumVersion)); - bool required = obj.Value<bool?>(nameof(IManifestDependency.IsRequired)) ?? true; + string uniqueID = obj.ValueIgnoreCase<string>(nameof(IManifestDependency.UniqueID)); + string minVersion = obj.ValueIgnoreCase<string>(nameof(IManifestDependency.MinimumVersion)); + bool required = obj.ValueIgnoreCase<bool?>(nameof(IManifestDependency.IsRequired)) ?? true; result.Add(new ManifestDependency(uniqueID, minVersion, required)); } return result.ToArray(); diff --git a/src/SMAPI/Framework/Serialisation/SmapiConverters/SemanticVersionConverter.cs b/src/SMAPI/Framework/Serialisation/SmapiConverters/SemanticVersionConverter.cs index 50181809..7ee7e29b 100644 --- a/src/SMAPI/Framework/Serialisation/SmapiConverters/SemanticVersionConverter.cs +++ b/src/SMAPI/Framework/Serialisation/SmapiConverters/SemanticVersionConverter.cs @@ -14,10 +14,10 @@ namespace StardewModdingAPI.Framework.Serialisation.SmapiConverters /// <param name="path">The path to the current JSON node.</param> protected override ISemanticVersion ReadObject(JObject obj, string path) { - int major = obj.Value<int>(nameof(ISemanticVersion.MajorVersion)); - int minor = obj.Value<int>(nameof(ISemanticVersion.MinorVersion)); - int patch = obj.Value<int>(nameof(ISemanticVersion.PatchVersion)); - string build = obj.Value<string>(nameof(ISemanticVersion.Build)); + int major = obj.ValueIgnoreCase<int>(nameof(ISemanticVersion.MajorVersion)); + int minor = obj.ValueIgnoreCase<int>(nameof(ISemanticVersion.MinorVersion)); + int patch = obj.ValueIgnoreCase<int>(nameof(ISemanticVersion.PatchVersion)); + string build = obj.ValueIgnoreCase<string>(nameof(ISemanticVersion.Build)); return new LegacyManifestVersion(major, minor, patch, build); } |