在 Json.Net 的 JsonConverter<> ReadJson() 中,为什么 reader..Value 为 null?

Jef*_*ege 6 c# json.net

我正在尝试为 NetTopologySuite 几何形状编写一个自定义 JsonConverter。

我的型号:

public class MyModel
{
    public string myName { get; set; }

    [JsonConverter(typeof(MyPolygonConverter))]
    public Polygon myPolygon { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我的转换器:

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.
    }
}
Run Code Online (Sandbox Code Playgroud)

我在做什么:

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]]]}}");
Run Code Online (Sandbox Code Playgroud)

发生了什么:

我的转换器正在被调用,但 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]
            ]
        ]
    }
}
Run Code Online (Sandbox Code Playgroud)

我需要获取“myPolygon”子级的所有内容并将其交给我的转换代码。在我见过的简单示例中, reader.Value 以字符串形式提供值。在这种情况下,它不会,很可能是因为“myPolygon”的子项不是单个值,而是一个复杂的 json 对象。

我已经有了用于解析作为单个 json 字符串提供的值的代码。那么我怎样才能以单个 json 字符串的形式获取孩子呢?

Bri*_*ers 12

我认为您对 JsonConverters 的工作原理有误解。读者不会向您提供原始 JSON。相反,它允许您一一单步执行 JSON 中的标记。

reader.Value为 null,因为您的转换器正在处理一个对象,而不是字符串,并且在调用您的转换器时,读取器位于令牌上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;
}
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

小提琴: https: //dotnetfiddle.net/OFSP1h