0

使用 Json.Net,您能否反序列化在不同 Json.Net 库中生成的 Json 数据(我使用的是 Json.Net 的 .Net4 和 windows phone 库)?这是我到目前为止所拥有的:

我有一个在 XNA (.Net 4) 中创建的地图编辑器,它可以使用 Json.Net (for .Net) 序列化和反序列化 Json 数据。我创建了一个结构来存储数据并指定我想要序列化的数据属性,如下所示:

[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 phone)。这个游戏有LevelData和Node,和Map Editor的struct和class完全一样。

Json.Net 为 .Net 4 和 windows phone 提供了不同的库。但是,它们似乎没有相同的功能。windows phone 游戏读取地图编辑器创建的 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

Map Editor 创建的 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 数据时。

4

2 回答 2

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

我没有在Vector2s 的特定情况下尝试过这个,所以不能确认它肯定会开箱即用。如果它不在您的ReadJson实现中,您可以开始考虑Value使用JsonReader. 这将返回一个您可以转换为其他类型并可能使用其中的数据object创建新的类型。Vector2如果这不起作用,您可能需要研究更复杂的JsonConverter情况,您对阅读器上的标记做出反应(TokenType等)

于 2012-04-17T23:16:52.647 回答
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();
    }
}
于 2013-02-16T16:25:16.227 回答