如何在 NewtonSoft.Json 中配置 returns json 而不是字符串的自定义转换器?

How do I configure a custom converter that returns json, instead of a string, in NewtonSoft.Json?

我有一个包含 NetTopologySuite 多边形的简单模型:

public class MyModel
{
    [Newtonsoft.Json.JsonConverter(typeof(MyPolygonConverter))]
    public NetTopologySuite.Geometries.Polygon poly { get; set; }
}

我已经构建了一个自定义转换器,使用 NetTopologySuite.IO.GeoJson:

public class MyPolygonConverter : JsonConverter<Polygon>
{
    public override void WriteJson(JsonWriter writer, Polygon value, JsonSerializer serializer)
    {
        var geoJsonSerializer = NetTopologySuite.IO.GeoJsonSerializer.Create();

        using var stringWriter = new StringWriter();
        using var jsonWriter = new JsonTextWriter(stringWriter);

        geoJsonSerializer.Serialize(jsonWriter, value);
        var geoJson = stringWriter.ToString();
        writer.WriteValue(geoJson);
    }
    ...
}

然后我创建一个模型对象并将其序列化:

var model = new MyModel
{
    poly = new Polygon(new LinearRing(new[]
    {
        new Coordinate(-100, 45),
        new Coordinate(-98, 45),
        new Coordinate(-99, 46),
        new Coordinate(-100, 45),
    }))
};

var geoJson = JsonConvert.SerializeObject(model, Formatting.None, 
    new JsonSerializerSettings
    {
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
        NullValueHandling = NullValueHandling.Ignore
    });

我得到的包含多边形作为转义的 GeoJson 字符串:

{
    "poly" : "{\"type\":\"Polygon\",\"coordinates\":[[[-100.0,45.0],[-98.0,45.0],[-99.0,46.0],[-100.0,45.0]]]}"
}

我想要的是 json 中的多边形,在 json 对象中:

{
    "poly" : {
        "type" : "Polygon",
        "coordinates" : [
            [
                [-100.0,45.0],
                [-98.0,45.0],
                [-99.0,46.0],
                [-100.0,45.0]
            ]
        ]
    }
}

我在想的是我根本不应该使用 JsonConverter,而是其他东西。

但是什么?

您可以使用 JsonWriter.WriteRawValue(string) 将原始 JSON 值直接写入 JSON 输出:

writer.WriteRawValue(geoJson);

也就是说,GeoJsonSerializer is a subclass of Newtonsoft's own JsonSerializer so you can just pass the incoming JsonWriter in to its Serialize()方法:

public override void WriteJson(JsonWriter writer, Polygon value, JsonSerializer serializer)
{
    var geoJsonSerializer = NetTopologySuite.IO.GeoJsonSerializer.Create();
    geoJsonSerializer.Serialize(writer, value);
}

演示 fiddle #1 here.

GeoJsonSerializer 和基础 class 的唯一区别是 NullValueHandling.Ignore 默认启用并且添加了几个转换器,所以你也可以只使用这个序列化程序来序列化 您的整个模型,从而无需将 [Newtonsoft.Json.JsonConverter(typeof(MyPolygonConverter))] 添加到您的模型:

var serializer = NetTopologySuite.IO.GeoJsonSerializer.CreateDefault(
    new JsonSerializerSettings
    {
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
        NullValueHandling = NullValueHandling.Ignore,
        Formatting = Formatting.Indented, // Or none, if you prefer
    });
var sb = new StringBuilder();
using (var sw = new StringWriter(sb))
using (var jsonWriter = new JsonTextWriter(sw))
    serializer.Serialize(jsonWriter, model);

var geoJson = sb.ToString();

演示 fiddle #2 here.