我使用Json。网首先看这个:
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 "
但是当我想对XNA矩形做同样的事情时,我得到一个错误。(只是用"using Microsoft.Xna.Framework;"代替了旧的using)
控制台输出为:"{X:-3 Y:6 Width:32 Height:32}"
,它抛出的错误是:"将值"{X:-3 Y:6 Width:32 Height:32}"转换为类型" Microsoft.Xna.Framework.Rectangle "出错。"
为什么会发生这种情况?
出了什么问题,我怎么解决这个??
我已经做了一些检查,这是导致异常的代码:
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);
}
对执行Convert工作的委托的实际调用无法找到此类型的转换器。调查原因,因为序列化器能够正确地序列化和反序列化其他类型。
编辑:这不起作用,因为XNA矩形类型定义为: [Serializable]
[TypeConverter(typeof(RectangleConverter))]
public struct Rectangle : IEquatable<Rectangle>
Json。. NET检索TypeConverter类型,并在其上调用此方法:
TypeConverter fromConverter = GetConverter(targetType);
if (fromConverter != null && fromConverter.CanConvertFrom(initialType))
{
// deserialize
}
矩形转换器有一个标志说"supportsStringConvert = false",所以尝试转换字符串到它失败。
这是反序列化该特定对象失败的原因。
我想到了一个让牛顿软下来的方法。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<Rectangle>(jsonData, settings);