使用Json.NET序列化XNA矩形

我正在使用Json.NET首先看看这个:

using System.Drawing; string json = JsonConvert.SerializeObject(new Rectangle(-3,6,32,32), Formatting.Indented); Console.WriteLine(json); Rectangle deserializedRectangle = JsonConvert.DeserializeObject(json); 

一切都按预期工作。 控制台输出为:“3,6,32,32”

但是当我想用XNA Rectangle做同样的事情时,我得到一个错误。 (只是用“使用Microsoft.Xna.Framework;”替换了旧的使用方法;)

控制台输出为:“{X:-3 Y:6宽度:32高度:32}”

它抛出的错误是:“转换值”{X:-3 Y:6宽度:32高度:32}时出错“输入’Microsoft.Xna.Framework.Rectangle’。”

  1. 为什么会这样?

  2. 什么是错的,我该如何解决这个问题?

我做了一些检查,这是导致exception的代码:

  public static bool TryConvert(object initialValue, CultureInfo culture, Type targetType, out object convertedValue) { return MiscellaneousUtils.TryAction(delegate { return Convert(initialValue, culture, targetType); }, out convertedValue); } 

对转换工作的委托的实际调用无法找到此类型的转换器。 调查原因,因为序列化程序能够正确地序列化和反序列化其他类型。

编辑:

这不起作用,因为XNA Rectangle类型定义为:

  [Serializable] [TypeConverter(typeof(RectangleConverter))] public struct Rectangle : IEquatable 

Json.NET检索TypeConverter类型,并在其上调用此方法:

  TypeConverter fromConverter = GetConverter(targetType); if (fromConverter != null && fromConverter.CanConvertFrom(initialType)) { // deserialize } 

RectangleConverter有一个标志“supportsStringConvert = false”,因此尝试将字符串转换为它失败。

这就是反序列化此特定对象失败的原因。

我找到了让Newtonsoft.Json(Json.Net)与XNA的Rectangle类玩得很好的方法。 首先,你的矩形应该是类的属性,所以你可以给它一个JsonConverter属性:

 public class Sprite { [JsonConverter(typeof(MyRectangleConverter))] public Rectangle Rectangle; } public class MyRectangleConverter : JsonConverter { public override void WriteJson( JsonWriter writer, object value, JsonSerializer serializer ) { var rectangle = (Rectangle)value; var x = rectangle.X; var y = rectangle.Y; var width = rectangle.Width; var height = rectangle.Height; var o = JObject.FromObject( new { x, y, width, height } ); o.WriteTo( writer ); } public override object ReadJson( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer ) { var o = JObject.Load( reader ); var x = GetTokenValue( o, "x" ) ?? 0; var y = GetTokenValue( o, "y" ) ?? 0; var width = GetTokenValue( o, "width" ) ?? 0; var height = GetTokenValue( o, "height" ) ?? 0; return new Rectangle( x, y, width, height ); } public override bool CanConvert( Type objectType ) { throw new NotImplementedException(); } private static int? GetTokenValue( JObject o, string tokenName ) { JToken t; return o.TryGetValue( tokenName, StringComparison.InvariantCultureIgnoreCase, out t ) ? (int)t : (int?)null; } } 

它可能会得到改善,所以反馈得到赞赏。

这是迄今为止我发现的最佳解决方案:

 private class XnaFriendlyResolver : DefaultContractResolver { protected override JsonContract CreateContract(Type objectType) { // Add additional types here such as Vector2/3 etc. if (objectType == typeof(Rectangle)) { return CreateObjectContract(objectType); } return base.CreateContract(objectType); } } 

并且只需配置Newtonsoft.JSON即可使用解析程序

 var settings = new JsonSerializerSettings() { ContractResolver = new XnaFriendlyResolver(), }; var rect = JsonConvert.DeserializeObject(jsonData, settings);