2011-07-28 25 views
5

Tôi đang sử dụng Json.NET Đầu tiên nhìn vào này:serializing XNA Rectangle với 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); 

Tất cả mọi thứ hoạt động như mong đợi. Đầu ra của bảng điều khiển là: "3, 6, 32, 32"

Nhưng khi tôi muốn làm điều tương tự với the XNA Rectangle, tôi gặp lỗi. (Chỉ cần thay thế cái cũ sử dụng với điều này "sử dụng Microsoft.Xna.Framework;")

Giao diện điều khiển đầu ra là: "{X: -3 Y: 6 Chiều rộng: 32 Chiều cao: 32}"

và lỗi mà nó ném là: "Lỗi chuyển đổi giá trị" {X: -3 Y: 6 Chiều rộng: 32 Chiều cao: 32} "để nhập 'Microsoft.Xna.Framework.Rectangle'."

  1. Tại sao điều này xảy ra?

  2. Có gì sai và cách khắc phục sự cố này?

+0

Cố gắng xây dựng Json.NET từ nguồn để bạn có thể xem ngoại lệ được ném vào trình gỡ lỗi.Câu trả lời cho # 1: có vẻ khá rõ ràng rằng nó chuyển đổi 'Hình chữ nhật' bằng cách sử dụng phương thức' ToString', thay vì trích xuất các giá trị thành viên riêng lẻ và không có phương thức nào để chuyển đổi nó trở lại. Tôi có thể đoán rằng Json.NET sử dụng các thuộc tính get/set công khai (như 'System.Drawing.Rectangle' có) và không" xem "các trường công khai * của Microsoft.Xna.Framework.Rectangle' *. –

Trả lời

5

tôi đã thực hiện một số kiểm tra, đây là mã gây ra ngoại lệ:

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

Cuộc gọi thực tế để các đại biểu để làm công việc Chuyển đổi không thể tìm thấy một chuyển đổi cho loại này. Điều tra nguyên nhân cho điều này, như serializer có thể serialize và deserialize các loại khác một cách chính xác.

EDIT:

này không làm việc, kể từ khi loại XNA Rectangle được định nghĩa là:

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

Json.NET lấy loại TypeConverter, và gọi phương pháp này vào nó:

TypeConverter fromConverter = GetConverter(targetType); 

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

RectangleConverter có một cờ nói "supportStringConvert = false", vì vậy cố gắng chuyển đổi một chuỗi thành chuỗi không thành công.

Đây là lý do khiến việc loại bỏ đối tượng cụ thể này không thành công.

+0

Chà, công việc tuyệt vời! Cảm ơn bạn đã tìm ra điều này. Bạn có bất kỳ ý tưởng nào về cách giải quyết vấn đề hoặc cách khắc phục sự cố không? – riki

+0

Bạn có thể thử tuần tự hóa nó thành một đối tượng khác (không phải chuỗi) nếu json.net cho phép nó. Tôi sẽ kiểm tra nó vào ngày mai –

+0

Có vẻ như bạn sẽ cần tạo một DTO đơn giản để tuần tự hóa/deserialize cấu trúc XNA Rectangle – MattDavey

2

Tôi đã tìm ra cách để có được Newtonsoft.Json (Json.Net) để chơi tốt đẹp với lớp XNA's Rectangle. Thứ nhất, hình chữ nhật của bạn phải là một tài sản của một lớp học, do đó bạn có thể cung cấp cho nó một thuộc tính 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; 
    } 
} 

Nó có thể có thể được cải thiện để phản hồi được đánh giá cao.

0

này đến nay là giải pháp tốt nhất mà tôi đã tìm thấy cho vấn đề này:

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

Và chỉ cần cấu hình Newtonsoft.JSON sử dụng resolver

var settings = new JsonSerializerSettings() { 
    ContractResolver = new XnaFriendlyResolver(), 
}; 

var rect = JsonConvert.DeserializeObject<Rectangle>(jsonData, settings); 
Các vấn đề liên quan