使用Json.NET序列化XNA矩形

时间:2011-07-28 05:26:00

标签: c# serialization xna json.net

我正在使用Json.NET 首先看一下:

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

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

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

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

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

  1. 为什么会这样?

  2. 出了什么问题,我该如何解决?

3 个答案:

答案 0 :(得分:5)

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

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

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

编辑:

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

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

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

  TypeConverter fromConverter = GetConverter(targetType);

  if (fromConverter != null && fromConverter.CanConvertFrom(initialType)) 
  {
       // deserialize
  }

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

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

答案 1 :(得分:2)

我找到了让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;
    }
}

它可能会得到改善,所以感谢反馈。

答案 2 :(得分:0)

这是我为此问题找到的最佳解决方案:

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<Rectangle>(jsonData, settings);