Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# json.net错误:意外的令牌反序列化对象_C#_Json_Json.net - Fatal编程技术网

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

C# json.net错误:意外的令牌反序列化对象,c#,json,json.net,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":

我有一个包含一些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
  }
]
这在反序列化时给了我前面提到的错误。有人能找到这个json的问题吗?我通过验证器检查了一下,它说没问题

它在“中心”后的空格上出错:如果我更改中心和LabelColor属性的顺序,则它在“LabelColor”后会以相同的方式出错:

以下是类型的转储:

LabelColor是一个OpenTK矢量4,Center是一个OpenTK矢量2,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;
}
这是矢量4转换器:

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();
    }
}
public类Vector4Converter:JsonConverter
{
公共覆盖布尔CanConvert(类型objectType)
{
返回objectType==typeof(Vector2);
}
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
reader.Read();
reader.Read();
var x=序列化程序。反序列化(读取器);
reader.Read();
reader.Read();
var y=序列化程序。反序列化(读取器);
reader.Read();
reader.Read();
var z=序列化程序。反序列化(读取器);
reader.Read();
reader.Read();
var w=序列化程序。反序列化(读取器);
返回新矢量4(x,y,z,w);
}
公共重写void WriteJson(JsonWriter编写器、对象值、JsonSerializer序列化器)
{
向量4向量值=(向量4)值;
writer.WriteStartObject();
writer.WritePropertyName(“X”);
WriteValue(vectorValue.X);
writer.WritePropertyName(“Y”);
WriteValue(vectorValue.Y);
writer.WritePropertyName(“Z”);
WriteValue(vectorValue.X);
writer.WritePropertyName(“W”);
WriteValue(vectorValue.Y);
writer.WriteEndObject();
}
}
Vector2Converter完全相同,只是它不包含Z和W属性的代码,并且名称不同

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


向量类可以在这里找到:

Tl;dr-问题出在您的
向量[X]转换器中。您读取了所有属性,但实际上并没有导航到对象的末尾。在返回具体对象的最后一行之前,需要一个额外的
reader.Read()

更深层次的解释:

在编写自定义转换器时,JSON.NET对
JsonReader
的状态很挑剔。您需要一直遍历到读卡器的末尾,而不管您是否真正需要剩余的数据(换句话说,您不能提前返回)

在本例中,您读取所需的值(W),然后立即返回一个新的具体对象,因为您拥有所需的所有数据。但是,
JsonReader
仍在检查属性节点,因此JSON.NET认为仍有数据等待反序列化。这就是为什么你会

完成反序列化对象后,在json字符串中找到其他文本

如果在
JsonConverter
中放置断点,并在标记中前进时观察
读取器
对象的状态,您可以自己看到这一点。关于最后一个问题,国家是:

...
Path: "LabelColor.W"
TokenType: Float
Value: 1.0
....
...
Path: "LabelColor"
TokenType: EndObject
Value: null
...
如果将
JsonReader
保持在该状态,您将得到一个错误。但是,如果执行最后一个
reader.Read()
,则状态为:

...
Path: "LabelColor.W"
TokenType: Float
Value: 1.0
....
...
Path: "LabelColor"
TokenType: EndObject
Value: null
...

现在JSON.NET很开心

读取的最简单方法是加载到
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();
    }
}
加载到
JToken
并按名称访问还允许发送方以任意顺序写入JSON属性,这是首选的,因为


另外,请注意,我修复了
WriteJson
中的几个错误(代码写了
X
Y
两次)在
CanConvert

中有一个错误,您是否也可以发布C#types?@UfukHacıoğullarıI已经发布了它们。@DanielA.White错误消息如下:Newtonsoft.Json.Json序列化异常类型的未处理异常发生在Newtonsoft.Json.dll中其他信息:反序列化对象时出现意外令牌:PropertyName。路径“[0]。居中”,第11行,位置14。“中心”后面的空格是什么:为什么你甚至需要一个转换器?十、 Y、Z和W是公共的、可写的字段,因此它们可以开箱即用地正确序列化。@dbc因为opentk中的vector*结构有相当多的字段,而不仅仅是X、Y、Z和W,它们会导致递归引用(例如public Vector2 Verticallright)。另外,只要有x、y、z和w,json的方式就更具可读性。由于这种奇怪之处,我建议使用基于JToken的阅读器,如dbc posted。感谢您对这个问题的解释。我实际上已经使用了dbc的答案,所以我会将其标记为已接受。此外,它应该鼓励人们正确地创建这些。JToken的解决方案比我拥有的要优雅得多,当然更优雅。希望我的解释能帮助其他试图弄明白JSON.NET为何会呕吐的人。干杯这个答案帮助我识别了我的
JsonConverter
中的一个问题。我的while循环停止条件是
while(reader.Read())
,这是不够的,因为我还有其他没有反序列化的对象。我必须更改while循环以检查
reader.TokenType
。在我的例子中,我正在检查
JsonToken.EndArray