在Json.Net的JsonConverter<> ReadJson()中,为什么reader..Value为空?
In Json.Net's JsonConverter<> ReadJson(), why is reader..Value null?
我正在尝试为 NetTopologySuite 几何体编写自定义 JsonConverter。
我的模特:
public class MyModel
{
public string myName { get; set; }
[JsonConverter(typeof(MyPolygonConverter))]
public Polygon myPolygon { get; set; }
}
我的转换器:
public class MyPolygonConverter : JsonConverter<Polygon>
{
public override Polygon ReadJson(JsonReader reader, Type objectType, Polygon existingValue,
bool hasExistingValue, JsonSerializer serializer)
{
var geoJson = (string)reader.Value;
// ... not relevant, because reader.Value is null.
}
}
我在做什么:
var deSerialized = JsonConvert.DeserializeObject<MyModel>("{\"myName\":\"My Name\",\"myPolygon\":{\"type\":\"Polygon\",\"coordinates\":[[[-100.0,45.0],[-98.0,45.0],[-99.0,46.0],[-100.0,45.0]]]}}");
发生了什么:
正在调用我的转换器,但 reader.Value 为空。
我在网上看到的例子都是使用(string)reader.Value来访问需要转换的json字符串。但在我的例子中 reader.Value 是空的。
我应该如何访问我需要转换的 JSON 字符串?
要清楚 - 我有一个模型 class,它包含 class 的 属性 - 多边形 - 我在需要转换的序列化时转换为 GeoJson回到那个 class,来自 GeoJson。
所以,我的起始 json 是:
{
"myName" : "My Name",
"myPolygon" : {
"type" : "Polygon",
"coordinates" : [
[
[-100.0, 45.0],
[-98.0, 45.0],
[-99.0, 46.0],
[-100.0, 45.0]
]
]
}
}
而且我需要获取“myPolygon”的 child 的所有内容,并将其交给我的转换代码。在我见过的简单示例中,reader.Value 以字符串形式提供值。在这种情况下,它不是,很可能是因为“myPolygon”的 child 不是单个值,而是一个复杂的 json object.
我已经有了用于解析作为单个 json 字符串提供的值的代码。那么我如何才能将 child 作为单个 json 字符串获取?
我认为您对 JsonConverters 的工作原理有误解。 reader 不会给你原始的 JSON。相反,它允许您逐个浏览 JSON 中的标记。
reader.Value
为空,因为您的转换器正在处理一个对象,而不是一个字符串,并且在调用您的转换器时,reader 位于 StartObject
标记上。您需要在循环中调用 reader.Read()
以在对象中前进以获取 属性 名称和值,直到到达 EndObject
标记。
这里有一个 fiddle 演示了该过程,尽管它实际上并未填充多边形。 https://dotnetfiddle.net/MQE6N5
如果你真的想要转换器中的 JSON 字符串,你可以从 reader 加载一个 JObject,然后调用它的 ToString() 方法:
public override Polygon ReadJson(JsonReader reader, Type objectType, Polygon existingValue, bool hasExistingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
string json = jo.ToString(Formatting.None);
Polygon poly = ConvertJsonToPolygon(json); // your conversion method
return poly;
}
IMO 更好的解决方案是使用 JObject 的功能来实际进行转换。您可以轻松地从 JObject 中选取值并从中填充您的多边形 class:
public override Polygon ReadJson(JsonReader reader, Type objectType, Polygon existingValue, bool hasExistingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
Polygon poly = new Polygon();
poly.type = (string)jo["type"];
poly.coordinates = jo["coordinates"].ToObject<double[][][]>(serializer);
return poly;
}
Fiddle: https://dotnetfiddle.net/OFSP1h
正如 Brian Rogers 所指出的,我的看法不正确。
但我真的不想一次一个标记地遍历 JsonReader 来构建我需要处理的 json 对象。
幸运的是,我不必这样做。 Json.Net 已经提供了执行此操作的工具:
public override Polygon ReadJson(JsonReader reader, Type objectType,
Polygon existingValue, bool hasExistingValue, JsonSerializer serializer)
{
var jObject = JObject.Load(reader);
var geoJson = jObject.ToString();
// Work with the geoJson string...
}
注意 - 这在对象不是数组时有效,在我的用例中它永远不会。如果您在原地做某事,则可能需要改用 JArray。如果您的用例规定您的对象可能是数组或对象,您可以通过检查 reader.TokenType == JsonToken.StartObject 来区分您需要使用的对象。我没有对此进行探讨,因为在我的用例中这是不可能的。
我正在尝试为 NetTopologySuite 几何体编写自定义 JsonConverter。
我的模特:
public class MyModel
{
public string myName { get; set; }
[JsonConverter(typeof(MyPolygonConverter))]
public Polygon myPolygon { get; set; }
}
我的转换器:
public class MyPolygonConverter : JsonConverter<Polygon>
{
public override Polygon ReadJson(JsonReader reader, Type objectType, Polygon existingValue,
bool hasExistingValue, JsonSerializer serializer)
{
var geoJson = (string)reader.Value;
// ... not relevant, because reader.Value is null.
}
}
我在做什么:
var deSerialized = JsonConvert.DeserializeObject<MyModel>("{\"myName\":\"My Name\",\"myPolygon\":{\"type\":\"Polygon\",\"coordinates\":[[[-100.0,45.0],[-98.0,45.0],[-99.0,46.0],[-100.0,45.0]]]}}");
发生了什么:
正在调用我的转换器,但 reader.Value 为空。
我在网上看到的例子都是使用(string)reader.Value来访问需要转换的json字符串。但在我的例子中 reader.Value 是空的。
我应该如何访问我需要转换的 JSON 字符串?
要清楚 - 我有一个模型 class,它包含 class 的 属性 - 多边形 - 我在需要转换的序列化时转换为 GeoJson回到那个 class,来自 GeoJson。
所以,我的起始 json 是:
{
"myName" : "My Name",
"myPolygon" : {
"type" : "Polygon",
"coordinates" : [
[
[-100.0, 45.0],
[-98.0, 45.0],
[-99.0, 46.0],
[-100.0, 45.0]
]
]
}
}
而且我需要获取“myPolygon”的 child 的所有内容,并将其交给我的转换代码。在我见过的简单示例中,reader.Value 以字符串形式提供值。在这种情况下,它不是,很可能是因为“myPolygon”的 child 不是单个值,而是一个复杂的 json object.
我已经有了用于解析作为单个 json 字符串提供的值的代码。那么我如何才能将 child 作为单个 json 字符串获取?
我认为您对 JsonConverters 的工作原理有误解。 reader 不会给你原始的 JSON。相反,它允许您逐个浏览 JSON 中的标记。
reader.Value
为空,因为您的转换器正在处理一个对象,而不是一个字符串,并且在调用您的转换器时,reader 位于 StartObject
标记上。您需要在循环中调用 reader.Read()
以在对象中前进以获取 属性 名称和值,直到到达 EndObject
标记。
这里有一个 fiddle 演示了该过程,尽管它实际上并未填充多边形。 https://dotnetfiddle.net/MQE6N5
如果你真的想要转换器中的 JSON 字符串,你可以从 reader 加载一个 JObject,然后调用它的 ToString() 方法:
public override Polygon ReadJson(JsonReader reader, Type objectType, Polygon existingValue, bool hasExistingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
string json = jo.ToString(Formatting.None);
Polygon poly = ConvertJsonToPolygon(json); // your conversion method
return poly;
}
IMO 更好的解决方案是使用 JObject 的功能来实际进行转换。您可以轻松地从 JObject 中选取值并从中填充您的多边形 class:
public override Polygon ReadJson(JsonReader reader, Type objectType, Polygon existingValue, bool hasExistingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
Polygon poly = new Polygon();
poly.type = (string)jo["type"];
poly.coordinates = jo["coordinates"].ToObject<double[][][]>(serializer);
return poly;
}
Fiddle: https://dotnetfiddle.net/OFSP1h
正如 Brian Rogers 所指出的,我的看法不正确。
但我真的不想一次一个标记地遍历 JsonReader 来构建我需要处理的 json 对象。
幸运的是,我不必这样做。 Json.Net 已经提供了执行此操作的工具:
public override Polygon ReadJson(JsonReader reader, Type objectType,
Polygon existingValue, bool hasExistingValue, JsonSerializer serializer)
{
var jObject = JObject.Load(reader);
var geoJson = jObject.ToString();
// Work with the geoJson string...
}
注意 - 这在对象不是数组时有效,在我的用例中它永远不会。如果您在原地做某事,则可能需要改用 JArray。如果您的用例规定您的对象可能是数组或对象,您可以通过检查 reader.TokenType == JsonToken.StartObject 来区分您需要使用的对象。我没有对此进行探讨,因为在我的用例中这是不可能的。