json.net error: unexpected token deserializing object
json.net error: unexpected token deserializing object
我有一个包含一些 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 的问题?我 运行 它通过了验证器,它说没问题。
它在 "Center" 之后的 space 上出错:如果我更改 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;
}
这里是 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();
}
}
Vector2Converter 完全相同,只是它不包含 Z 和 W 属性的代码,而且名称不同。
反序列化过程将成功通过第一个,但甚至无法进入第二个。
矢量 类 可以在这里找到:https://github.com/opentk/opentk/tree/develop/Source/OpenTK/Math
Tl;dr - 问题出在您的 Vector[X]Converters
上。您阅读了所有属性,但实际上并没有导航到对象的末尾。您需要在 return 您的具体对象的最后一行之前添加一个额外的 reader.Read()
。
更深层次的解释:
JSON.NET 在编写自定义转换器时对 JsonReader
的状态很挑剔。你需要一直遍历到reader的末尾,不管你是否真的需要剩下的数据(也就是说,你不能return早)。
在此示例中,您读取了所需的值 (W),然后立即 return 编辑了一个新的具体对象,因为您拥有所需的所有数据。但是,JsonReader
仍在检查 属性 节点,因此 JSON.NET 认为仍有数据等待反序列化。这就是为什么你得到
Additional text found in json string after finishing deserializing object
如果您在 JsonConverter
中放置一个断点并在您通过标记前进时观察 reader
对象的状态,您可以自己看到这一点。最后一个,状态是:
...
Path: "LabelColor.W"
TokenType: Float
Value: 1.0
....
如果您将 JsonReader
保持在该状态,您将收到错误消息。但是,如果你最后做一个reader.Read()
,那么状态是:
...
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 属性,这是首选,因为 JSON spec states that property name/value pairs are unordered.
此外,请注意我修正了 WriteJson
中的几个错误(代码将 X
和 Y
写了两次)和 CanConvert
.[=18= 中的一个错误]
我有一个包含一些 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 的问题?我 运行 它通过了验证器,它说没问题。
它在 "Center" 之后的 space 上出错:如果我更改 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;
}
这里是 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();
}
}
Vector2Converter 完全相同,只是它不包含 Z 和 W 属性的代码,而且名称不同。
反序列化过程将成功通过第一个,但甚至无法进入第二个。
矢量 类 可以在这里找到:https://github.com/opentk/opentk/tree/develop/Source/OpenTK/Math
Tl;dr - 问题出在您的 Vector[X]Converters
上。您阅读了所有属性,但实际上并没有导航到对象的末尾。您需要在 return 您的具体对象的最后一行之前添加一个额外的 reader.Read()
。
更深层次的解释:
JSON.NET 在编写自定义转换器时对 JsonReader
的状态很挑剔。你需要一直遍历到reader的末尾,不管你是否真的需要剩下的数据(也就是说,你不能return早)。
在此示例中,您读取了所需的值 (W),然后立即 return 编辑了一个新的具体对象,因为您拥有所需的所有数据。但是,JsonReader
仍在检查 属性 节点,因此 JSON.NET 认为仍有数据等待反序列化。这就是为什么你得到
Additional text found in json string after finishing deserializing object
如果您在 JsonConverter
中放置一个断点并在您通过标记前进时观察 reader
对象的状态,您可以自己看到这一点。最后一个,状态是:
...
Path: "LabelColor.W"
TokenType: Float
Value: 1.0
....
如果您将 JsonReader
保持在该状态,您将收到错误消息。但是,如果你最后做一个reader.Read()
,那么状态是:
...
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 属性,这是首选,因为 JSON spec states that property name/value pairs are unordered.
此外,请注意我修正了 WriteJson
中的几个错误(代码将 X
和 Y
写了两次)和 CanConvert
.[=18= 中的一个错误]