Serializing XNA Rectangle with Json.NET

后端 未结 3 1688
野趣味
野趣味 2020-12-19 13:20

I\'m using Json.NET First look at this:

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


        
相关标签:
3条回答
  • 2020-12-19 13:31

    I've done some checking, this is the code that causes the exception:

        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);
        }
    

    The actual call to the delegate that does the Convert work cannot find a convertor for this type. Investigating the cause for this, as the serializer is able to serialize and deserialize other types correctly.

    EDIT:

    This does not work, since the XNA Rectangle type is defined as:

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

    Json.NET retrieves TypeConverter type, and calls this method on it:

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

    The RectangleConverter has a flag saying "supportsStringConvert = false", so attempting to convert a string into it fails.

    This is the reason that deserializing this specific object is failing.

    0 讨论(0)
  • 2020-12-19 13:42

    This is by far the best solution I've found for this issue:

    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);
      }
    }
    

    And just configure Newtonsoft.JSON to use the resolver

    var settings = new JsonSerializerSettings() {
      ContractResolver = new XnaFriendlyResolver(),
    };
    
    var rect = JsonConvert.DeserializeObject<Rectangle>(jsonData, settings);
    
    0 讨论(0)
  • 2020-12-19 13:44

    I figured out a way to get Newtonsoft.Json (Json.Net) to play nice with XNA's Rectangle class. First, your rectangle should be a property of a class so you can give it a JsonConverter attribute:

    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;
        }
    }
    

    It could probably be improved so feedback is appreciated.

    0 讨论(0)
提交回复
热议问题