当前位置: 首页 > 知识库问答 >
问题:

在JSON.NET的JSONConverterReadJson()中,为什么Reader..value为空?

苏运良
2023-03-14

我正在尝试为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字符串来获取呢?

共有2个答案

盛建德
2023-03-14

正如布莱恩·罗杰斯指出的那样,我看事情的眼光不对。

但是我真的不想一次一个令牌地在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来区分需要使用哪一个。我没有探索过这一点,因为在我的用例中这是不可能的。

杨乐意
2023-03-14

我认为您对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

 类似资料:
  • 问题内容: 我正在学习SwiftUI。我遇到了“ GeometryReader”。我想知道为什么以及何时使用它? 问题答案: 更新 自从发布答案以来,我还写了一篇有关GeometryReader如何工作的文章。 查看它以获取更详细的说明:https : //swiftui-lab.com/geometryreader-to-the-rescue/ GeometryReader是一个视图,使您可以访

  • 问题内容: 给定 为什么 在链接到电话吗? 问题答案: 因为没有ed 或其他值从链接到构造函数。 请注意,将返回一个新对象。 解决方案是使用value或from 的值或其他函数调用。

  • 问题内容: 作为测试某些代码的附带结果,我编写了一个小函数来比较使用array.push方法与直接寻址(array [n] = value)的速度。令我惊讶的是,推送方法通常显示出更快的速度,尤其是在Firefox和Chrome中。出于好奇:有人对此有解释吗?您可以找到测试(单击“数组方法比较”) 问题答案: 各种各样的因素都在起作用,大多数JS实现使用平面数组,如果以后需要的话,可以转换为稀疏存

  • 下面按钮,测试3 那个 disabled 不生效,为什么?但是后面 {{options.isDisabled}} 显示是 false,必须要像 测试4 那样加上 .value 才可以,但是 测试1 没有加 .value 确实正常的,这是为什么?

  • 我正在编写一些生成PDF文档的代码。我正在为可编辑的PDF表单生成Acroform复选框注释,这些注释在我测试的大多数PDF阅读器中都表现得非常好:Chrome、Firefox、Mac Preview和PDF Element 6。然而,我真的很难在Acrobat Reader中得到正确的渲染。 我一直在工作一个最小的示例PDF,只包含一个复选框,没有其他内容。 以下是当我悬停/单击复选框时,在Ac

  • 我被这个JavaSpring Boot问题困住了。我已经在loadUserByUsername方法的返回语句中填写了自动权限:this.get权限(user)。但是当我打印身份验证对象时,它说授予权限为空: UsernamePasswordAuthenticationToken[Principal=mark,Credentials=PROTECTED],Authenticated=true,Det