json.net错误:意外的令牌反序列化对象

Pat*_*ick 1 c# json json.net

我有一个带有一些json的文件,它是由json.net生成的:

[
  {
    "$type": "Dashboard.Gauges.LabelGaugeSeed, Dashboard",
    "Text": "blah",
    "LabelColor": {
      "X": 1.0,
      "Y": 1.0,
      "Z": 1.0,
      "W": 1.0
    },
    "Center": {
      "X": 0.0,
      "Y": 0.0
    },
    "CharacterWidth": 0.05,
    "CharacterHeight": 0.1,
    "LineThickness": 0.01,
    "TextCentering": 0.5
  }
]
Run Code Online (Sandbox Code Playgroud)

在反序列化时,这给了我上面提到的错误.任何人都可以找到这个json的问题?我通过验证器运行它,它说没关系.

它在"中心"之后的空格上出错:如果我更改了Center和LabelColor属性的顺序,那么在"LabelColor"之后它会以相同的方式出错:

这是一个类型的转储:

LabelColor是OpenTK Vector4,Center是OpenTK Vector2,LabelGaugeSeed如下:

public class LabelGaugeSeed : IGaugeSeed
{
    public IGauge Grow()
    {
        return new LabelGauge(this);
    }

    public string Text;
    [JsonConverter(typeof(Vector4Converter))]
    public Vector4 LabelColor;
    [JsonConverter(typeof(Vector2Converter))]
    public Vector2 Center;
    public float CharacterWidth;
    public float CharacterHeight;
    public float LineThickness;
    public float TextCentering;
}
Run Code Online (Sandbox Code Playgroud)

这是Vector4Converter:

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

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        reader.Read();
        reader.Read();
        var x = serializer.Deserialize<float>(reader);

        reader.Read();
        reader.Read();
        var y = serializer.Deserialize<float>(reader);

        reader.Read();
        reader.Read();
        var z = serializer.Deserialize<float>(reader);

        reader.Read();
        reader.Read();
        var w = serializer.Deserialize<float>(reader);

        return new Vector4(x, y, z, w);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        Vector4 vectorValue = (Vector4)value;

        writer.WriteStartObject();

        writer.WritePropertyName("X");
        writer.WriteValue(vectorValue.X);

        writer.WritePropertyName("Y");
        writer.WriteValue(vectorValue.Y);

        writer.WritePropertyName("Z");
        writer.WriteValue(vectorValue.X);

        writer.WritePropertyName("W");
        writer.WriteValue(vectorValue.Y);

        writer.WriteEndObject();
    }
}
Run Code Online (Sandbox Code Playgroud)

Vector2Converter完全相同,除了它不包含Z和W属性的代码,并且名称不同.

反序列化过程将成功通过第一个,但甚至不进入第二个.

Vector类可以在这里找到:https://github.com/opentk/opentk/tree/develop/Source/OpenTK/Math

Nat*_*ini 9

Tl;博士 - 问题出在你的身上Vector[X]Converters.您阅读了所有属性,但实际上并未导航到对象的末尾.reader.Read()在返回具体对象的最后一行之前,您需要一个额外的权限.

我在自己面前遇到过这种情况,所以对于其他任何从谷歌这样做的人,我会进一步解释一下.

问题 - JSON.NET对于JsonReader你在编写自定义转换器时如何离开状态很挑剔.无论您是否确实需要剩余数据(换句话说,您不能提前返回),您需要一直遍历到读者的末尾.

在此示例中,您读取了所需的值(W),然后在完成反序列化后立即返回一个新的具体对象.但是,JsonReader仍在检查属性节点,因此JSON.NET认为仍有数据要反序列化.这就是你得到的原因

完成反序列化对象后在json字符串中找到的附加文本

你可以自己看到这个,如果你在你的内部放置一个断点,JsonConverter并在reader你通过令牌前进时观察对象的状态.在最后一个,国家是:

...
Path: "LabelColor.W"
TokenType: Float
Value: 1.0
....
Run Code Online (Sandbox Code Playgroud)

如果你离开JsonReader那个状态,你会收到一个错误.但是,如果你最后一个reader.Read(),那么状态是:

...
Path: "LabelColor"
TokenType: EndObject
Value: null
...
Run Code Online (Sandbox Code Playgroud)

现在JSON.NET很开心!

  • 这个答案帮助我确定了`JsonConverter`中的问题。我的while循环停止条件是`While(reader.Read())`,这还不够,因为我还有其他对象尚未进行反序列化。我必须更改while循环以检查`reader.TokenType`。就我而言,我正在检查`JsonToken.EndArray`。 (2认同)

dbc*_*dbc 7

执行读取的最简单方法是JToken按名称加载并访问属性,如下所示:

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

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var token = JToken.Load(reader);
        var vec = new Vector4();

        if (token["X"] != null)
            vec.X = (float)token["X"];
        if (token["Y"] != null)
            vec.Y = (float)token["Y"];
        if (token["Z"] != null)
            vec.Z = (float)token["Z"];
        if (token["W"] != null)
            vec.W = (float)token["W"];
        return vec;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        Vector4 vectorValue = (Vector4)value;

        writer.WriteStartObject();

        writer.WritePropertyName("X");
        writer.WriteValue(vectorValue.X);

        writer.WritePropertyName("Y");
        writer.WriteValue(vectorValue.Y);

        writer.WritePropertyName("Z");
        writer.WriteValue(vectorValue.Z);

        writer.WritePropertyName("W");
        writer.WriteValue(vectorValue.W);

        writer.WriteEndObject();
    }
}
Run Code Online (Sandbox Code Playgroud)

加载到a JToken并按名称访问还允许发件人以任何顺序编写JSON属性,这是首选,因为JSON规范声明属性名称/值对是无序的.

另外,请注意我固定的一对夫妇的错误WriteJson(代码写的X,并Y两次)和一个错误CanConvert.