1

The code below shows how I'm reading / deserializing a geoJSON file into an ExpandoObject using Newtonsoft.Json.

As I'm looping through the items how do I test if the item contains the attribute place?

Or can I do this in a LINQ query?

As can be seen I've tried several methods from this page none are working

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);
    }
Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
Holly
  • 307
  • 1
  • 8
  • 17

1 Answers1

2

Newtonsoft returns a JObject when DeserializeObject method is called.

dynamic jsonFeatures = JsonConvert.DeserializeObject(jsonContent);

JObject has a Contains method you can use like this:

jsonFeatures.ContainsKey("your_key");

or even in nested objects like this:

jsonFeatures.nestedObject.ContainsKey("your_key");

Maybe it's also useful to take a look at libraries like GeoJson-Net

I would try to convert the Json file to a Class using services like this and then deserialize it to this Class.

You can play around with this fiddle:

https://dotnetfiddle.net/wwu20E

And if you want to play with geoJson.net, I've prepared something that retrieves a file similar as the one you'll probably have:

https://dotnetfiddle.net/47ohAA

Then you can check if the properties are populated.

Tena
  • 600
  • 4
  • 14
  • Every item / Feature in jsonFeatures are likely to have different a set of attributes If I can filter just "place" I can then deal with those I need. I did try `item.ContainsKey("place")` I got an error about no overload method for ContainsKey? Maybe I should of said the geojson file was created using ogr2ogr from a small openstreetmap test file it is only point data so simple to pass I will look at GeoJson-Net – Holly Jun 04 '21 at 20:57
  • 1
    Pay attention to the method used (DeserializeObject) instead of Deserialize because they don't return the same object. – Tena Jun 06 '21 at 18:17
  • I don't see a way of doing this from a file stream `dynamic jsonFeatures = JsonConvert.DeserializeObject(reader);` Am I missing something? Error CS1503 Argument 1: cannot convert from 'Newtonsoft.Json.JsonReader' to 'string'. – Holly Jun 07 '21 at 10:06
  • 1
    You can only use string as a parameter for DeserializeObject, you can read it in the Newtonsoft documentation linked below, that means that you need to convert your stream into an string: https://learn.microsoft.com/en-us/dotnet/api/system.io.filestream?redirectedfrom=MSDN&view=net-5.0 – Tena Jun 07 '21 at 13:59
  • 1
    I updated my answer with a few examples, one with string, another with geojson.net. If you feel this is helpful, please mark the comments as usefull or the answer. – Tena Jun 07 '21 at 17:26