【问题标题】:How do you test if an attribute exists in a dynamic JSON file如何测试动态 JSON 文件中是否存在属性
【发布时间】:2021-06-04 13:38:42
【问题描述】:

下面的代码显示了我如何使用 Newtonsoft.Json 将 geoJSON 文件读取/反序列化为 ExpandoObject。

当我在遍历项目时,如何测试项目是否包含属性 place?

或者我可以在 LINQ 查询中执行此操作吗?

可以看出我已经尝试了this page 的几种方法,都没有工作

var PPL = new List<string> { "city", "farm", "hamlet", "isolated_dwelling", "neighbourhood", "quarter", "suburb", "town", "village" };
....  
  JsonSerializer serializer = new JsonSerializer();

    using (FileStream s = File.Open(jsonFile, FileMode.Open))
    using (StreamReader sr = new StreamReader(s, Encoding.UTF8))
    using (JsonReader reader = new JsonTextReader(sr))
    {
        while (reader.Read())
        {
            // deserialize only when there's "{" character in the stream
            if (reader.TokenType == JsonToken.StartObject)
            {
                dynamic jsonFeatures = serializer.Deserialize<ExpandoObject>(reader);
                foreach (var item in jsonFeatures.features)
                {
                    if(HasAttr(item, "place"))
                    //if (((IDictionary<String, object>)item).ContainsKey("place"))
                    
                    //if (item.ContainsKey("place"))
                    {
                        // Some fixed attributes
                        var osm_id = item.properties.osm_id ?? string.Empty;
                    string name = item.properties.name ?? string.Empty;
                    string is_in = item.is_in ?? string.Empty;
                    string Place = item.place ?? string.Empty;

                    string geom = JsonConvert.SerializeObject(item.geometry);
                    bool IsPPL = PPL.Contains(Place, StringComparer.OrdinalIgnoreCase);

                    if (IsPPL)
                    {
                        Console.WriteLine("name: {0} is_in: {1} Place: {2} geom: {3} ", name, is_in, Place, geom);
                    }

                    }
                }
            }
        }
    }

    private static bool HasAttr(ExpandoObject expando, string key)
    {
        return ((IDictionary<string, Object>)expando).ContainsKey(key);
    }

【问题讨论】:

    标签: c# .net json.net


    【解决方案1】:

    当调用 DeserializeObject 方法时,Newtonsoft 返回一个JObject

    dynamic jsonFeatures = JsonConvert.DeserializeObject(jsonContent);
    

    JObject 有一个 Contains 方法,您可以像这样使用:

    jsonFeatures.ContainsKey("your_key");
    

    甚至在这样的嵌套对象中:

    jsonFeatures.nestedObject.ContainsKey("your_key");
    

    也许看看像GeoJson-Net这样的库也很有用

    我会尝试使用 thisdeserialize it to this Class 等服务将 Json 文件转换为 Class。

    你可以玩弄这个小提琴:

    https://dotnetfiddle.net/wwu20E

    如果你想玩 geoJson.net,我准备了一些东西,可以检索与你可能拥有的文件类似的文件:

    https://dotnetfiddle.net/47ohAA

    然后您可以检查属性是否已填充。

    【讨论】:

    • jsonFeatures 中的每个项目/功能都可能具有不同的一组属性如果我可以过滤“地点”,那么我可以处理我需要的那些。我确实尝试过item.ContainsKey("place") 我收到一个关于 ContainsKey 没有重载方法的错误?也许我应该说geojson文件是使用来自一个小的openstreetmap测试文件的ogr2ogr创建的,它只是点数据,所以很容易通过我会看看GeoJson-Net
    • 注意使用的方法(DeserializeObject)而不是Deserialize,因为它们返回的不是同一个对象。
    • 我没有从文件流dynamic jsonFeatures = JsonConvert.DeserializeObject(reader); 中看到这样做的方法@ 我错过了什么吗?错误 CS1503 参数 1:无法从“Newtonsoft.Json.JsonReader”转换为“字符串”。
    • DeserializeObject 只能使用字符串作为参数,可以在下面链接的 Newtonsoft 文档中阅读,这意味着您需要将流转换为字符串:docs.microsoft.com/en-us/dotnet/api/…
    • 我用几个例子更新了我的答案,一个是字符串,另一个是 geojson.net。如果您觉得这有帮助,请将 cmets 标记为有用或答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-03
    • 2014-08-11
    • 2018-12-25
    • 2011-03-01
    • 1970-01-01
    相关资源
    最近更新 更多