c# Json retrieve a specific node with his level - c#

I've created two c# classes and then deserialize the Json returned to work with it natively.
class structureTree
{
public structureChildren[] children { get; set; }
}
class structureChildren
{
public structureChildren[] children { get; set; }
public string myentity { get; set; }
public bool sonGuide { get; set; }
public string from { get; set; }
public Int64 structureId { get; set; }
public string to { get; set; }
}
The Data returned is like this
[
{
"children": [
{
"children": [
{
"children": [
{
"children": [],
"myentity": "ENT2_A",
"from": "2019-10-01",
"structureId": 34353,
"to": null
},
{
"children": [
{
"children": [],
"myentity": "ENT3_A",
"from": "2019-10-01",
"structureId": 34349,
"to": null
},
{
"children": [],
"myentity": "ENT3_B",
"from": "2019-10-01",
"structureId": 34351,
"to": null
}
],
"myentity": "ENT2_B",
"from": "2019-10-01",
"structureId": 34348,
"to": null
}
],
"myentity": "ENT1_A",
"from": "2019-10-01",
"structureId": 34348,
"to": null
}
],
"myentity": "ENT0_A",
"from": "2019-10-01",
"structureId": 34348,
"to": null
}
]
}
]
I need to get all "myentity" elements and if it's possible in which level resides.
If not possible obtain level, another way is get all "myentity" for each level.

Probably there are much better and elegant ways of doing this. This is without thinking on it much:
void Main()
{
var st = JsonConvert.DeserializeObject<List<structureTree>>(myjson);
List<Tuple<string,int>> entities = new List<System.Tuple<string, int>>();
foreach (var stc in st)
{
foreach (var sc in stc.children)
{
GetMyEntity(entities, sc, 0);
}
}
foreach (var e in entities)
{
Console.WriteLine($"{e.Item1}, {e.Item2}");
}
}
void GetMyEntity(List<Tuple<string,int>> entities, structureChildren c, int level)
{
entities.Add(Tuple.Create(c.myentity,level));
level++;
foreach (var sc in c.children)
{
GetMyEntity(entities, sc, level);
}
}
class structureTree
{
public structureChildren[] children { get; set; }
}
class structureChildren
{
public structureChildren[] children { get; set; }
public string myentity { get; set; }
public bool sonGuide { get; set; }
public string from { get; set; }
public Int64 structureId { get; set; }
public string to { get; set; }
}
static readonly string myjson = #"[
{
""children"": [
{
""children"": [
{
""children"": [
{
""children"": [],
""myentity"": ""ENT3_A"",
""from"": ""2019-10-01"",
""structureId"": 34353,
""to"": null
},
{
""children"": [
{
""children"": [],
""myentity"": ""ENT3_B"",
""from"": ""2019-10-01"",
""structureId"": 34349,
""to"": null
},
{
""children"": [],
""myentity"": ""ENT3_C"",
""from"": ""2019-10-01"",
""structureId"": 34351,
""to"": null
}
],
""myentity"": ""ENT2_A"",
""from"": ""2019-10-01"",
""structureId"": 34348,
""to"": null
}
],
""myentity"": ""ENT1_1"",
""from"": ""2019-10-01"",
""structureId"": 34348,
""to"": null
}
]
}
]
}
]";
Output:
, 0
ENT1_1, 1
ENT3_A, 2
ENT2_A, 2
ENT3_B, 3
ENT3_C, 3

You can do it in two ways, with a stack/queue or recursion. I personally prefer stacks since recursion is hard(er) to debug. This is a quick draft. I'm sure someone else can give you a fancy recursion version with Linq, but I think this illustrates the steps you need to take better.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var structure = new StructureTree();
var currentStack = new Stack<StructureChildren>(structure.children);
var nextStack = new Stack<StructureChildren>();
var flatStructure = new List<KeyValuePair<int, string>>();
int currentLevel = 0;
bool loop = true;
while (loop)
{
var currentItem = currentStack.Pop();
foreach (var child in currentItem.children)
nextStack.Push(child);
flatStructure.Add(new KeyValuePair<int, string>(currentLevel, currentItem.myentity));
if (currentStack.Count == 0)
{
if (nextStack.Count == 0)
break;
currentLevel++;
currentStack = new Stack<StructureChildren>(nextStack);
nextStack.Clear();
}
}
}
public class StructureTree
{
public StructureChildren[] children { get; set; }
}
public class StructureChildren
{
public StructureChildren[] children { get; set; }
public string myentity { get; set; }
public bool sonGuide { get; set; }
public string from { get; set; }
public Int64 structureId { get; set; }
public string to { get; set; }
}
}
PS: Please look into the naming convention provided by Microsoft. Class names should be CapitalizedAtEveryWord and property names too. Your current naming scheme is typically used for Java, not C#.

Related

How to recursively traverse down a nested object with n levels and refer back to any grandparent level objects on kth level, and change those objects

I need to recurse down an object with arbitrarily deep nesting of child objects. On each level of nesting I reach, I need to refer back to any (potentially all) of the objects on levels I've already been through, i.e. any grandparents of the current child object I am at. I then need to set properties on any of those referenced parent objects based on the current object's state. The properties I'm setting is determined by JSON.
Some values will be determined at runtime (those that are randomly generated in the example below) and others will just be strings from the JSON.
Minimum reproducible example:
Take this JSON as input:
{
"name": "foo",
"targetChildren": [
"baz",
"quux"
],
"valsFromChildren": [],
"runtimeValsFromChildren": [],
"childObjects": [
{
"name": "baz",
"valToGive": "giftFromBaz",
"targetChildren": [
"qux"
],
"valsFromChildren": [],
"runtimeValsFromChildren": [],
"childObjects": [
{
"name": "qux",
"valToGive": "giftFromQux"
},
{
"name": "quux",
"valToGive": "giftFromQuux"
}
]
}
]
}
The targetChildren refer to the names of the child/grandchild objects from which I want to get values and give them to "this" object. The valsFromChildren List should be populated based on that connection - the children with the matching names from targetChildren should put their valToGive value in the valsFromChildren List on the object targeting them. We can assume that there will be no duplicate names.
runtimeValsFromChildren is a List that gets filled with random numbers that are computed by the child object that is giving the value to the parent.
C# console app (needs to be Dotnet version 6):
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Collections;
var json = "{\"name\":\"foo\",\"targetChildren\":[\"baz\",\"quux\"],\"valsFromChildren\":[],\"runtimeValsFromChildren\":[],\"childObjects\":[{\"name\":\"baz\",\"valToGive\":\"giftFromBaz\",\"targetChildren\":[\"qux\"],\"valsFromChildren\":[],\"runtimeValsFromChildren\":[],\"childObjects\":[{\"name\":\"qux\",\"valToGive\":\"giftFromQux\"},{\"name\":\"quux\",\"valToGive\":\"giftFromQuux\"}]}]}";
var obj = JsonSerializer.Deserialize<Obj>(json);
DoRecursion(obj);
var newObjJson = JsonSerializer.Serialize(obj);
static Obj DoRecursion(Obj obj)
{
if (obj.ChildObjects == null || obj.ChildObjects.Count <= 0)
return obj;
foreach (var child in obj.ChildObjects)
{
var parent = obj;
if (parent.TargetChildren != null && parent.TargetChildren.Contains(child.Name))
{
// Give the values to the parent that is targeting them.
parent.ValsFromChildren.Add(child.ValToGive);
parent.RuntimeValsFromChildren.Add(child.RuntimeVal);
}
return DoRecursion(child);
}
return obj;
}
class Obj
{
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonPropertyName("valToGive")]
public string ValToGive { get; set; }
[JsonPropertyName("targetChildren")]
public List<string> TargetChildren { get; set; }
[JsonPropertyName("valsFromChildren")]
public List<string> ValsFromChildren { get; set; }
[JsonPropertyName("runtimeValsFromChildren")]
public List<int> RuntimeValsFromChildren { get; set; }
[JsonPropertyName("childObjects")]
public List<Obj> ChildObjects { get; set; }
[JsonIgnore]
public int RuntimeVal => new Random().Next(0, 100);
}
Desired output in JSON:
{
"name": "foo",
"targetChildren": [
"baz",
"quux"
],
"valsFromChildren": [
"giftFromBaz",
"giftFromQuux"
],
"runtimeValsFromChildren": [
31,
88
],
"childObjects": [
{
"name": "baz",
"valToGive": "giftFromBaz",
"targetChildren": [
"qux"
],
"valsFromChildren": [
"giftFromQux"
],
"runtimeValsFromChildren": [
43
],
"childObjects": [
{
"name": "qux",
"valToGive": "giftFromQux"
},
{
"name": "quux",
"valToGive": "giftFromQuux"
}
]
}
]
}
Actual output:
{
"name": "foo",
"targetChildren": [
"baz",
"quux"
],
"valsFromChildren": [
"giftFromBaz"
],
"runtimeValsFromChildren": [
43
],
"childObjects": [
{
"name": "baz",
"valToGive": "giftFromBaz",
"targetChildren": [
"qux"
],
"valsFromChildren": [
"giftFromQux"
],
"runtimeValsFromChildren": [
60
],
"childObjects": [
{
"name": "qux",
"valToGive": "giftFromQux"
},
{
"name": "quux",
"valToGive": "giftFromQuux"
}
]
}
]
}
I need the valsFromChildren List on the object with name foo to include giftFromQuux (a grand child that I want to grab from the 3rd level down). At the moment it only manages to get the value from its immediate child ("baz"), not its grand child ("quux"). It needs to be a recursive solution that should work for grandparents n levels down the nesting.
I would also like to know how to not mutate the original object but instead return a copy at a different memory address, i.e. have the method not have side effects.
Thanks.
Okay so here is your c# class (I used this website)
public class ChildObject
{
public string name { get; set; }
public string valToGive { get; set; }
public List<string> targetChildren { get; set; }
public List<string> valsFromChildren { get; set; }
public List<int> runtimeValsFromChildren { get; set; }
public List<ChildObject> childObjects { get; set; }
}
public class Root
{
public string name { get; set; }
public List<string> targetChildren { get; set; }
public List<string> valsFromChildren { get; set; }
public List<int> runtimeValsFromChildren { get; set; }
public List<ChildObject> childObjects { get; set; }
}
So you just have to do :
Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(theJsonString);
And then when you finish modifying thing do:
string myNewJson = JsonConvert.SerializeObject(myDeserializedClass);
Frankly it is not totally clear on your intent/desired result here SO here is a console app that walks the deserialized and then the altered object a few ways. Perhaps you can build from this a bit. This is a bit "chatty" to give you some ideas where you can go with this.
Here is a working copy of this sample: https://dotnetfiddle.net/qakv6n
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
Console.WriteLine("Hello World");
var json = "{\"name\":\"foo\",\"targetChildren\":[\"baz\",\"quux\"],\"valsFromChildren\":[],\"runtimeValsFromChildren\":[],\"childObjects\":[{\"name\":\"baz\",\"valToGive\":\"giftFromBaz\",\"targetChildren\":[\"qux\"],\"valsFromChildren\":[],\"runtimeValsFromChildren\":[],\"childObjects\":[{\"name\":\"qux\",\"valToGive\":\"giftFromQux\"},{\"name\":\"quux\",\"valToGive\":\"giftFromQuux\"}]}]}";
var obj = JsonSerializer.Deserialize<JsonObj>(json);
Console.WriteLine($#"Hello World {obj.Name} has {obj.TargetChildren.Count} targets");
foreach (var item in obj.TargetChildren.Select((value, i) => new { i, value }))
{
Console.WriteLine($#"Hello item: {item} has targets");
var value = item.value;
var index = item.i;
Console.WriteLine($#"x: index:{index} val: {value} ");
}
DoRecursion(obj);
var newObjJson = JsonSerializer.Serialize(obj);
Console.WriteLine($#"serial {newObjJson} ");
foreach (var rv in obj.RuntimeValsFromChildren)
{
Console.WriteLine($#"Count {rv} ");
}
foreach (var v in obj.ValsFromChildren)
{
Console.WriteLine($#"Vals {v} ");
}
}
static JsonObj DoRecursion(JsonObj obj)
{
if (obj.ChildObjects == null || obj.ChildObjects.Count <= 0)
return obj;
foreach (var child in obj.ChildObjects)
{
Console.WriteLine($#"Hello Recursing Name:{child.Name} Count: {obj.ChildObjects.Count} kiddos");
var g = obj.ChildObjects.Where(co => co.Name == child.Name)
.Select(x => new{Name= x.Name, Val= x.ValToGive}).First();
Console.WriteLine($"g:{g.Name} v:{g.Val}");
var newObjJson = JsonSerializer.Serialize(obj);
var parent = obj;
if (parent.TargetChildren != null && parent.TargetChildren.Contains(child.Name))
{
// Give the values to the parent that is targeting them.
parent.ValsFromChildren.Add(child.ValToGive);
parent.RuntimeValsFromChildren.Add(child.RuntimeVal);
}
return DoRecursion(child);
}
return obj;
}
class JsonObj
{
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonPropertyName("valToGive")]
public string ValToGive { get; set; }
[JsonPropertyName("targetChildren")]
public List<string> TargetChildren { get; set; }
[JsonPropertyName("valsFromChildren")]
public List<string> ValsFromChildren { get; set; }
[JsonPropertyName("runtimeValsFromChildren")]
public List<int> RuntimeValsFromChildren { get; set; }
[JsonPropertyName("childObjects")]
public List<JsonObj> ChildObjects { get; set; }
[JsonIgnore]
public int RuntimeVal => new Random().Next(0, 100);
}
}

Change value in json, when other value is looking for

I have Json where i have 2 objects. I would like to know how to change value in my json, when other value is looking for. For example i would like to change "speciality" to "Warrior" for Person who's "Name" is Harry.
It's my Json
{
"Person": [
{
"Speciality": "Archer",
"Id": 432742,
"Name": "Charlie",
"Surname": "Evans",
"Items": [
"Bow",
"Arrow",
]
},
{
"Speciality": "Soldier",
"Id": 432534,
"Name": "Harry",
"Surname": "Thomas",
"Items": [
"Gun",
"Knife",
]
}
],
"Monster": [
{
"Name": "Papua",
"Skills": [
"Jump",
"SlowWalk",
]
},
{
"Name": "Geot",
"Skills": [
"Run",
"Push",
]
}
]
}
My classes
public class Person
{
public string Speciality { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public List<string> Items { get; set; }
}
public class Monster
{
public string Name { get; set; }
public List<string> Skills { get; set; }
}
public class Root
{
public List<Person> People { get; set; }
public List<Monster> Monsters { get; set; }
}
I tried something like this:
var result = JsonSerializer.Deserialize<Root>(jsonfile)
for (int i = 0; i < result.People.Count; ++i)
{
result.Where(w => w.Person.Name == "Harry").ToList().ForEach(s => s.Person.Speciality = "Warrior");
}
Thanks in advance for some help.
Your can use foreach loop
var result = JsonSerializer.Deserialize<Root>(jsonfile);
foreach (var person in result.Person)
{
if(person.Name == "Harry"){
person.Speciality = "";
}
}

Pick out specific, optional key from metavalues object in JSON and store into my class

I'm struggling to make this conversion happen, and not sure it's entirely feasible. My JSON from a third party could look like this:
{
"equipments": [
{
"serialNumber": "11-17-053",
"equipmentType_id": "589dda4952172110008870c7",
"created": 1508856453875,
"fieldOffice_id": "594af5425fbfca00111a0c20",
"clients_id": [],
"notes": "",
"isInService": true,
"metavalues": {
"0t78nzhp9w265avlvt": {
"item_ids": [
33121
]
},
"7ogz4kehqh8h3cwip8": {
"item_ids": [
33128
]
}
},
"schedules": [],
"id": "59ef52854d40a9009c787596"
},
{
"serialNumber": "11-17-054",
"equipmentType_id": "589dda4952172110008870c7",
"created": 1508856453875,
"fieldOffice_id": "594af5425fbfca00111a0c20",
"clients_id": [],
"notes": "",
"isInService": true,
"metavalues": {
"0t78nzhp9w265avlvt": {
"item_ids": [
33121
]
},
"7ogz4kehqh8h3cwip8": {
"item_ids": [
33128
]
}
},
"schedules": [],
"id": "59ef52854d40a9009c787597"
},
{
"serialNumber": "8-17-022",
"equipmentType_id": "589dda4952172110008870c7",
"created": 1505326964589,
"fieldOffice_id": "594af5425fbfca00111a0c20",
"clients_id": [],
"notes": "",
"isInService": true,
"metavalues": {
"0t78nzhp9w265avlvt": {
"item_ids": [
33121
]
},
"7ogz4kehqh8h3cwip8": {
"item_ids": [
33128
]
}
},
"schedules": [],
"id": "59b9777480e426009d01d48d"
},
{
"serialNumber": "22A-17-001",
"equipmentType_id": "589dda4952172110008870c7",
"created": 1504908025733,
"fieldOffice_id": "58b74b080c206710004ff726",
"clients_id": [
"59bbfdf5725cd00012fb15d8"
],
"notes": "",
"isInService": true,
"metavalues": {
"0t78nzhp9w265avlvt": {
"item_ids": [
33122
]
},
"7ogz4kehqh8h3cwip8": {
"item_ids": [
33128
]
},
"g99idmcqyuo2na9e6l": "YARD",
"709pm94prt2tpjt90y": 5,
"bgen1h4i5b6f8xa1kh": "9/8/2017 7:18:24 PM",
"yvtvsl8dedudqjtdud": "0.00000, 0.00000",
"aj3h2b5fdbic9s72m3": "Parex",
"8wt1re82xidjiv8rzi": "YARD"
},
"schedules": [],
"id": "59b312f93256d5009c4a73fb"
},....
This is obviously not a complete example, but should help get my question across.
Is there a way to create a C# class that pulls in certain fields only if they exist from the "metavalues" array?
My current class is as follows which works to get the data, but not exactly how I want.
public class Equipment
{
[JsonProperty("serialNumber")]
public string SerialNumber { get; set; }
public string equipmentType_id { get; set; }
public bool isInService { get; set; }
public List<string> clients_Id { get; set; }
public string fieldOffice_id { get; set; }
[JsonProperty("id")]
public string EquipmentId { get; set; }
[JsonProperty("metavalues")]
public Dictionary<string, object> metavalues { get; set; }
}
What I'm after, is taking the key of "g99idmcqyuo2na9e6l" which is optional in the metavalues, and store it in a property called "LeaseName".
I tried the following to no avail.
public class Equipment
{
[JsonProperty("serialNumber")]
public string SerialNumber { get; set; }
public string equipmentType_id { get; set; }
public bool isInService { get; set; }
public List<string> clients_Id { get; set; }
public string fieldOffice_id { get; set; }
[JsonProperty("id")]
public string EquipmentId { get; set; }
[JsonProperty("g99idmcqyuo2na9e6l")]
public string LeaseName { get; set; }
}
If I try to make a class for the metavalues section, I get an exception indicating that JSON.NET can't convert it to my object, hence why I used the Dictionary<string, object> option.
EDIT # 1: The accepted answer works for me, but for those who stumble upon this and truly need a property name from a nested array you could try the following.
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
if (metavalues != null)
{
if (metavalues.ContainsKey("g99idmcqyuo2na9e6l"))
{
string _LeaseName = (string)metavalues["g99idmcqyuo2na9e6l"];
LeaseName = _LeaseName;
}
}
}
I think my edit approach is a bit overkill but just throwing this out there.
Yes, this is possible, but since the lease value is still one level down in the JSON you need an intermediate class to hold it (to replace the dictionary).
public class Equipment
{
...
[JsonProperty("metavalues")]
public MetaValues MetaValues { get; set; }
}
public class MetaValues
{
[JsonProperty("g99idmcqyuo2na9e6l")]
public string LeaseName { get; set; }
}
Fiddle: https://dotnetfiddle.net/Ddqzc7

Deserializing a Json list of objects c#

ok so im not entirely sure how to explain this but ill give it my best shot. i have deserialisation from json working on singular objects, but when i get a list of the objects in json form, it doesnt work, and there are a few extra details outside of the singular objects when in a list of the objects.
the line of code im pretty sure is the problem is
var model = JsonConvert.DeserializeObject<DeserializedObjects.BlockList>(JObject.Parse(json).ToString());
but i cannot figure out how to solve it.
anyway.
this is where the multiple data objects in json from come from:
public static async Task<DeserializedObjects.BlockList> GetUpToTenBlocks(int height)
{
var JData = (dynamic)new JObject();
JData.height = height;
String uri = String.Concat(partialApi, "/local/chain/blocks-after");
var response = await client.PostAsync(uri, new StringContent(JData.ToString(), Encoding.UTF8, "application/json"));
var content = response.Content;
{
var json = await content.ReadAsStringAsync();
var model = JsonConvert.DeserializeObject<DeserializedObjects.BlockList>(JObject.Parse(json).ToString());
Console.WriteLine(model.AtIndex[1].difficulty);
return model;
}
}
which is deserialized to:
public class PrevBlockHash
{
public string data { get; set; }
}
public class Block
{
public int timeStamp { get; set; }
public string signature { get; set; }
public PrevBlockHash prevBlockHash { get; set; }
public int type { get; set; }
public List<object> transactions { get; set; }
public int version { get; set; }
public string signer { get; set; }
public long height { get; set; }
}
public class Datum
{
public object difficulty { get; set; }
public List<object> txes { get; set; }
public Block block { get; set; }
public string hash { get; set; }
}
public class BlockList
{
public List<Datum> AtIndex { get; set; }
}
and this is the json payload:
{
"data": [
{
"difficulty": 11763927507942,
"txes": [],
"block": {
"timeStamp": 167479,
"signature": "bb062d9b5f132b39b9e56de2413bf04928af009587446621da7afd351d
15a2ce7b5504450acf41bc3b19ab71e9bf34722005239d93f05a2318130f85118df40c",
"prevBlockHash": {
"data": "d4875ad2fc74dacfa89a13f24159d14555d3766f4fe2d708a7596f84eba88
31b"
},
"type": 1,
"transactions": [],
"version": 1744830465,
"signer": "00a30788dc1f042da959309639a884d8f6a87086cda10300d2a7c3a0e0891
a4d",
"height": 1001
},
"hash": "f70898011d7343a0823de9c9cf263de29ddf2c16bb78cea626b9af90ea7ec260"
},
{
"difficulty": 11625594628802,
"txes": [],
"block": {
"timeStamp": 167561,
"signature": "116dedf43dd06b9ca634db0e20e06cc93337cdba155bced4d843ece4cc
9a57487d58e9a34d8a0e19bf71d3b7facb15179a87767f0063ebbce7c940cd545d5f01",
"prevBlockHash": {
"data": "f70898011d7343a0823de9c9cf263de29ddf2c16bb78cea626b9af90ea7ec
260"
},
"type": 1,
"transactions": [],
"version": 1744830465,
"signer": "6ecd181da287c9ccb0075336de36427f25cbc216dc6b1f0e87e35e41a39f6
3fe",
"height": 1002
},
"hash": "77b5644c35e0d0d51f8bb967d0d92e0ddb03c4ede6632cb3b7651b7394617562"
},
{
"difficulty": 11538802895169,
"txes": [],
"block": {
"timeStamp": 167624,
"signature": "982574132fdc99b6f484acdd3f1cb5229b2bf78ad7b4e9af3d7a1873da
b987401f8bf808ff749aca70c503f490db1411b6cd89dbb0c1daa24fd580f91d3d9601",
"prevBlockHash": {
"data": "77b5644c35e0d0d51f8bb967d0d92e0ddb03c4ede6632cb3b7651b7394617
562"
},
"type": 1,
"transactions": [],
"version": 1744830465,
"signer": "26a3ac4b24647c77dc87780a95e50cb8d7744966e4569e3ac24e52c532c0c
d0d",
"height": 1003
},
"hash": "1a6d52c6317150d1839790da2c1481d714038c869842f769affbec0fdeec9861"
}
]
}
Try this:
var model = JsonConvert.DeserializeObject<DeserializedObjects.BlockList>(json);
Console.WriteLine(model.data[1].difficulty);
along with, also:
public class BlockList
{
public List<Datum> data { get; set; }
}

Get selected results from a Json file

This is an example of the Json files that I want to work with:
{
"type": "FeatureCollection",
"totalFeatures": 213,
"features": [
{
"type": "Feature",
"id": "world_contries.1",
"geometry": {
"type": "MultiPolygon",
"coordinates": [
[
[
[
65.53080749511719,
37.248600006103516
],
[
65.6272964477539,
37.33319854736328
]
]
]
]
},
"geometry_name": "geom",
"properties": {
"name": "Afghanistan",
"iso_3_code": "AFG",
"iso_2_code": "AF",
"area": 65209,
"name_1": "Afghanistan",
"gmi_cntry": "AFG",
"region": "Asia",
"pop2005": 25067407,
"name_12": "Afghanistan"
}
},
{
"type": "Feature",
"id": "world_contries.2",
"geometry": {
"type": "MultiPolygon",
"coordinates": [
[
[
[
19.282489776611328,
42.18553924560547
],
[
19.397319793701172,
42.31707000732422
]
]
]
]
},
"geometry_name": "geom",
"properties": {
"name": "Albania",
"iso_3_code": "ALB",
"iso_2_code": "AL",
"area": 2740,
"name_1": "Albania",
"gmi_cntry": "ALB",
"region": "Europe",
"pop2005": 3153731,
"name_12": "Albania"
}
},
]
}
In this type of files I want to have the geometry type and coordinates of all features.
I'm currently using this method to access the file:
public static List<string> getCoords(string path)
{
//List<string> layers = new List<string>();
string url = path;
WebRequest request = WebRequest.Create(url);
request.ContentType = "application/json";
request.Method = "GET";
try
{
WebResponse response = request.GetResponse();
StreamReader responseStream = new StreamReader(response.GetResponseStream());
string responseText = responseStream.ReadToEnd();
JObject o = JObject.Parse(responseText);
dynamic array = JsonConvert.DeserializeObject(responseText);
string type = array["features"].Children()["geometry"]["type"];
response.Close();
}
catch (WebException)
{
;
}
return null;
}
But it's not working. For instance:
array["features"].Children()["geometry"]["type"]
This is an Newtonsoft.JSon.Linq.JEnumerable
When I'm debugging in my Visual Studio, in the results view I can read "MultiPolygon", but I do I extract the value?
I used json2csharp (http://json2csharp.com) to generate some C# classes that match the JSON you provided..
public class Geometry
{
public string type { get; set; }
public List<List<List<List<double>>>> coordinates { get; set; }
}
public class Properties
{
public string name { get; set; }
public string iso_3_code { get; set; }
public string iso_2_code { get; set; }
public int area { get; set; }
public string name_1 { get; set; }
public string gmi_cntry { get; set; }
public string region { get; set; }
public int pop2005 { get; set; }
public string name_12 { get; set; }
}
public class Feature
{
public string type { get; set; }
public string id { get; set; }
public Geometry geometry { get; set; }
public string geometry_name { get; set; }
public Properties properties { get; set; }
}
public class RootObject
{
public string type { get; set; }
public int totalFeatures { get; set; }
public List<Feature> features { get; set; }
}
You could then modify your code so that it deserializes to the RootObject and it will be alot easier to work with instead of dynamic types...
var myObject = JsonConvert.DeserializeObject<RootObject>(responseText);
Then you could access it like this...
foreach (var feature in myObject.features)
{
var geometryType = feature.geometry.type;
....
}
You can simply loop through the JEnumerable to extract each geometry type :
.....
dynamic array = JsonConvert.DeserializeObject(json);
var types = array["features"].Children()["geometry"]["type"];
foreach (string type in types)
{
Console.WriteLine(type);
}

Categories

Resources