2012-04-17 9 views
0

Json.Netを使用すると、別のJson.Netライブラリで生成されたJsonデータを逆シリアル化できますか(Json.Netの.Net4およびWindows Phoneライブラリを使用しています) ?異なるJson.Netライブラリによって生成されたJsonデータを逆シリアル化する

私はJson.Net(.Net用)を使ってJsonデータをシリアライズして逆シリアル化できるXNA(.Net 4)で作成したマップエディタを持っています。私は、データを格納し、私が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の携帯電話のXNAゲームを持っていますJson.Net(Windows電話用)を使用して、マップエディタから作成されたJsonデータを読み込みます。このゲームにはLevelDataとNodeがあり、Map Editorの構造体やクラスとまったく同じです。

Json.Netは、.Net 4とWindows phone用の別のlibを提供します。しかし、彼らは同じ機能を持っていないようです。 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 

この問題は、メンバー変数をpublicにしてプライベートではなくすることで解決できます。しかし、それはそれはベクトル2認識していないと文句を言い:

{ 
    "RowCount": 20, 
    "ColCount": 20, 
    "NodeSize": 25, 
    "LevelNodes": [ 
     { 
      "ID": 1, 
      "Position": "12, 12", 
      "Type": 1, 
      "Neighbours": [ 
       2, 
       21 
      ] 
     } 
    ], 
    "Buildings": [] 
} 
:マップエディタで作成されたJSONデータである

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 

:デバッグウィンドウで印刷以下のものを

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

編集:データをシリアル化およびデシリアライズする方法は次のとおりです。

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をシリアライズおよびデシリアライズすることができ、それはプライベートなJSONのプロパティをサポートし、ベクトル2。問題は、マップエディタで生成されたjsonデータをWindows電話アプリケーションで逆シリアル化する場合です。

答えて

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秒の特定のケースでこれを試していません。 ReadJsonの実装に含まれていない場合は、JsonReaderValueプロパティを使用して調べることができます。これにより、objectが返され、他のタイプにキャストし、可能であればVector2という新しいデータを作成することができます。それでも解決しない場合は、あなたがリーダー(TokenType、など)にトークンに反応するも、より複雑なJsonConverterを検討する必要があるかもしれません

+0

おかげで、私は、私はそのルートを下る必要はありませんでした期待していました他の多くのオブジェクトタイプでこの問題に遭遇します。 .Net版ではなぜそれができるのか理解できませんが、Windows phoneはありません。多分それは銀色のためですか? – Benzino

+0

私は確かにこの問題に遭遇したことがなく、 'Vector2'を見ていませんでした。(私はXNAの仕事をしていませんでした)私はそれに特有の何かを見ることができません(' struct'ではなく、 'DateTime ')。あなたがデータをどのようにシリアル化しているかを見てみましょう。 'TypeNameHandling'と' TypeNameAssemblyFormat'オプションは 'JsonSerializer'を与えていますか? – MrMDavidson

+0

私は問題を見ていると思います。私は実際にJsonSerializer自体ではなく、JsonConvertを使用しています。元の投稿を編集してデータのシリアル化方法を示しました。私はまた、次のJsonSettings 'Formatting.Indented、TypeNameHandling.All、FormatterAssemblyStyle.Full'を使ってみましたが、Vector2についてまだ不平を言っていました。 – Benzino

0

ベクトル2のまたは他のシリアライズとデシリアライズの問題を持つ将来の視聴者へのより完全な答え類似のオブジェクト。私はストレートWindowsで問題を抱えていますが、OPのようなWinPhoneではありません。

それはセットアップにシリアライズオブジェクト自体ではなく、そのように、シリアル化する必要が各ベクトル2プロパティでカスタムベクトル2のデシリアライザ可能です:すべてのベクトル2プロパティを飾るすることから私たちを保持します

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

読むとさらに

、私が使用しているコンバータの完全な実装、および実装書き込みは、次のとおりです。私は疑うよう

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(); 
    } 
} 
関連する問題