我正在尝试为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字符串?
需要说明的是,我有一个模型类,它包含一个类的属性--Polygon,我在序列化时将其转换为GeoJson,我需要从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”的所有内容都交给我的转换代码。在我看到的简单示例中,reader.value提供了字符串形式的值。在本例中,它不是,很可能是因为“myPolygon”的子对象不是一个值,而是一个复杂的json对象。
我已经有了解析作为单个json字符串提供的值的代码。那么,我如何将孩子作为一个json字符串来获取呢?
我认为您对JsonConverters的工作方式有一个误解。读取器不会给您原始的JSON。它为您提供了一个阅读器,允许您逐个逐个地遍历JSON中的令牌。
reader.value
为空,因为您的转换器处理的是对象,而不是字符串,并且在调用转换器时,读取器位于startObject
标记上。您需要在循环中调用reader.read()
,以在对象中前进以获取属性名称和值,直到到达EndObject
令牌。
下面是一个演示该过程的小提琴,尽管它并没有实际填充多边形。https://dotnetfiddle.net/mqe6n5
如果您真的需要转换器中的JSON字符串,您可以从读取器加载一个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中选择值并从中填充Polygon类:
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;
}
小提琴:https://dotnetfiddle.net/ofsp1h
正如布莱恩·罗杰斯指出的那样,我看事情的眼光不对。
但是我真的不想一次一个令牌地在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来区分需要使用哪一个。我没有探索过这一点,因为在我的用例中这是不可能的。