使用Json.Net,你可以反序列化在不同的Json.Net库中生成的Json数据(我使用的是Json.Net的.Net4和windows phone libs)吗?这就是我到目前为止所做的:
我在XNA(.Net 4)中创建了一个Map Editor,它可以使用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;
}
}
Node类如下:
[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手机)。这个游戏有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而不是private来解决此问题。但后来它抱怨说它无法识别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,它支持私有json属性和Vector2。问题是当我在Windows Phone应用程序中对地图编辑器中生成的json数据进行反序列化时。
答案 0 :(得分: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
实施中没有,您可以开始考虑使用Value
上的JsonReader
属性。这会返回一个object
,您可以将其转换为其他类型,并可能使用来自的数据创建新的Vector2
。如果这不起作用,您可能需要查看更为复杂的JsonConverter
,其中您对阅读器上的令牌作出反应(TokenType
等)
答案 1 :(得分: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();
}
}