2012-04-17 103 views
0

使用Json.Net,您是否可以反序列化在不同的Json.Net庫中生成的Json數據(我使用的是Json.Net的.Net4和windows手機庫) ?這是我到目前爲止:反序列化由不同的Json.Net生成的Json數據lib

我有一個在XNA(.Net 4)中創建的地圖編輯器,可以使用Json.Net(對於.Net)對Json數據進行序列化和反序列化。我創建了一個結構來存儲數據,並指定哪些數據的屬性我想serizalized,就像這樣:

[JsonObject(MemberSerialization.OptIn)] 
public struct LevelData 
{ 
    [JsonProperty(PropertyName = "RowCount")] 
    private int RowCount; 

    [JsonProperty(PropertyName = "ColCount")] 
    private int ColCount; 

    [JsonProperty(PropertyName = "NodeSize")] 
    private int NodeSize; 

    [JsonProperty(PropertyName = "LevelNodes")] 
    private List<Node> LevelNodes; 

    public LevelData(int rowCount, int colCount, int nodeSize, List<Node> nodes) 
    { 
     RowCount = rowCount; 
     ColCount = colCount; 
     NodeSize = nodeSize; 
     LevelNodes = nodes; 
    } 
} 

和節點類如下:

[JsonObject(MemberSerialization.OptIn)] 
public class Node 
{ 
    [JsonProperty(PropertyName = "ID")] 
    private int mId; 

    [JsonProperty(PropertyName = "Position")] 
    private Vector2 mPosition; 

    [JsonProperty(PropertyName = "Type")] 
    private NodeType mType; 

    [JsonProperty(PropertyName = "Neighbours")] 
    private List<int> mNeighbours; 

    .... 
} 

我也有一個Windows Phone的XNA遊戲,它讀入從地圖編輯器創建的Json數據,也使用Json.Net(用於Windows Phone)。這個遊戲有LevelData和Node,它們和Map Editor結構和類完全一樣。

Json.Net爲.Net 4和windows phone提供了一個不同的庫。但是,它們似乎沒有相同的功能。當Windows手機遊戲從地圖編輯器創建的JSON數據讀取,它未能反序列化數據,並顯示以下錯誤:

Error getting value from 'mRowCount' on 'LevelData'. 

隨着調試窗口中的以下打印出來:

A first chance exception of type 'System.FieldAccessException' occurred in mscorlib.dll 
A first chance exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll 
A first chance exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll 

我可以通過使成員變量公開而不是私有來解決這個問題。但隨後抱怨說,它不承認Vector2:

Error converting value "12, 12" to type 'Microsoft.Xna.Framework.Vector2'. Line 8, position 27. 

隨着調試窗口中的以下打印出來:

A first chance exception of type 'System.Exception' occurred in Newtonsoft.Json.dll 
A first chance exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll 

,其中,通過地圖編輯器創建的JSON數據:

{ 
    "RowCount": 20, 
    "ColCount": 20, 
    "NodeSize": 25, 
    "LevelNodes": [ 
     { 
      "ID": 1, 
      "Position": "12, 12", 
      "Type": 1, 
      "Neighbours": [ 
       2, 
       21 
      ] 
     } 
    ], 
    "Buildings": [] 
} 

編輯:這是我如何序列化和反序列化的數據。

String json = Json.ConvertToJson<LevelData>(levelData); 

public static class Json 
{ 
    // Serialize Object to Json 
    public static string ConvertToJson<T>(T obj) 
    { 
     return JsonConvert.SerializeObject(obj, Formatting.Indented); 
    } 

    public static T ConvertFromJson<T>(string json) 
    { 
     T result = JsonConvert.DeserializeObject<T>(json); 

     return result; 
    } 
} 

剛一說明:我可以序列化和反序列化的地圖編輯器(.NET)就好了,它支持私人JSON屬性和Vector2的JSON。問題是當我去反序列化在Windows Phone應用程序中在地圖編輯器中生成的json數據時。

回答

1

你可以嘗試的是爲Vector2類型引入你自己的轉換器;

[JsonObject(MemberSerialization.OptIn)] 
public class Node { 
    ... 

    [JsonConverter(typeof(Vector2Converter))] 
    public Vector2 Position { get; set; } 

    ... 
} 

Vector2Converter是一種從Json.Net的JsonConverter獲得。

public class Vector2Converter : JsonConverter { 
    public override bool CanConvert(Type objectType) { 
    return (objectType == typeof(Vector2)); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { 
    return serializer.Deserialize<Vector2>(reader); 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { 
    // Implement this if you're serialising back into JSON 
    throw new NotImplementedException(); 
    } 
} 

我沒有在Vector2特定情況下嘗試這個S因此無法確認它肯定會工作的開箱。如果它不在您的ReadJson實施中,您可以開始考慮使用JsonReader上的Value屬性。這會返回一個object,您可以將其轉換爲其他類型,並可能使用其中的數據創建新的Vector2。如果不工作,你可能需要尋找到更多地參與JsonConverter,你的令牌反應的讀者(TokenType等)

+0

謝謝,我希望我沒有走這條路線,因爲我懷疑我會遇到許多其他對象類型的問題。不明白他們爲什麼可以爲.Net版本做,但沒有Windows手機。也許這是爲了silverlight? – Benzino 2012-04-18 13:19:28

+0

我以前從來沒有遇到過這個問題,並且看過'Vector2'(我沒有做過任何XNA工作),我看不到任何特殊的東西(除了是'struct',但是'DateTime' ')。另一件要看的是你如何序​​列化數據?你在給'JsonSerializer'選擇什麼'TypeNameHandling'和'TypeNameAssemblyFormat'選項? – MrMDavidson 2012-04-18 14:43:25

+0

我想我看到了這個問題。我實際上使用JsonConvert,而不是JsonSerializer本身。我編輯了我的原始帖子,以顯示如何序列化數據。我也試過使用下面的JsonSettings'Formatting.Indented,TypeNameHandling.All,FormatterAssemblyStyle.Full',但它仍然抱怨Vector2。 – Benzino 2012-04-18 21:00:32

0

更完整的答案有問題序列化和反序列化未來的觀衆Vector2的或其他類似的物體。我在直接Windows中遇到問題,而不是像OP那樣的WinPhone。

這是可能的設置序列化對象本身,而不是需要每個Vector2財產上的自定義Vector2解串器被序列化,像這樣:

var settings = new JsonSerializerSettings(); 
settings.Converters.Add(new Vector2Converter()); 
YourType yourObj = JsonConvert.DeserializeObject<YourType>(fileContents, settings); 

這使我們不必裝點每一個Vector2財產。

此外,全面落實我使用的轉換器,具有讀取和寫操作實現,方法是:

public class Vector2Converter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) { 
     return (objectType == typeof(Vector2)); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { 
     JObject jsonObject = JObject.Load(reader); 
     var properties = jsonObject.Properties().ToList(); 
     return new Vector2 
     { 
      X = (float)properties[0].Value, 
      Y = (float)properties[1].Value 
     }; 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { 
     Vector2 v = (Vector2)value; 
     writer.WriteStartObject(); 
     writer.WritePropertyName("X"); 
     serializer.Serialize(writer, v.X); 
     writer.WritePropertyName("Y"); 
     serializer.Serialize(writer, v.Y); 
     writer.WriteEndObject(); 
    } 
}