How to convert JSON to object with C# - c#

I am having trouble accessing the properties in my json file. I need to create a c# object with it too. It is not able to work properly. This requires the need to drill down several classes, where I cannot find any other documentation on it, as most use a very simple json file.
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties":
{
"TYPE": "COASTAL",
"R_STATEFP": "28",
"L_STATEFP": ""
},
"geometry":
{
"type": "LineString",
"coordinates": [
[ -88.453654, 30.196584 ],
[ -88.428301, 30.198511 ],
[ -88.404581, 30.206162 ],
[ -88.401466, 30.210172 ],
[ -88.430332, 30.208548 ],
[ -88.442654, 30.202314 ],
[ -88.453444, 30.201236 ],
[ -88.465713, 30.202540 ],
[ -88.500011, 30.214044 ],
[ -88.506999, 30.214348 ],
[ -88.502752, 30.210506 ],
[ -88.493523, 30.205945 ],
[ -88.453654, 30.196584 ]
]
}
},
//repeated 100+ times
]
}
This is my classes file:
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace MyApp
{
public class FeatureCollection
{
public string type{ get; set; }
public List<Feature> features{ get; set; }
[JsonConstructor]
public FeatureCollection(JObject i)
{
var typeProp = i.GetType().GetProperty("type");
this.type = typeProp.GetValue(i) as string;
JArray features = (JArray)i.GetValue("features");
this.features = new List<Feature>();
foreach (JObject f in features)
{
this.features.Add(new Feature(f));
Console.Write(features);
}
}
}
public class Feature
{
public string type;
public Property properties;
public Geometry geometry;
[JsonConstructor]
public Feature(JObject i)
{
var typeProp = i.GetType().GetProperty("type");
this.type = typeProp.GetValue(i) as string;
var prop = i.GetValue("properties") as JObject;
this.properties = new Property(prop);
var geo = i.GetValue("geometry") as JObject;
this.geometry = new Geometry(geo);
}
}
public class Property
{
public string TYPE;
public string R_STATEFP;
public string L_STATEFP;
[JsonConstructor]
public Property(JObject i)
{
var typeProp = i.GetType().GetProperty("TYPE");
this.TYPE = typeProp.GetValue(i) as string;
var typeR = i.GetType().GetProperty("type");
this.R_STATEFP = typeR.GetValue(i) as string;
var typeL = i.GetType().GetProperty("type");
this.L_STATEFP = typeL.GetValue(i) as string;
}
}
public class Geometry
{
public string type;
public List<Coord> coordinates;
[JsonConstructor]
public Geometry(JObject i)
{
var typeProp = i.GetType().GetProperty("type");
this.type = typeProp.GetValue(i) as string;
JArray coordinates = (Newtonsoft.Json.Linq.JArray)i.GetValue("coordinates");
this.coordinates = new List<Coord>();
foreach (JArray c in coordinates)
{
this.coordinates.Add(new Coord(c));
}
}
}
public class Coord
{
public double longitude;
public double latitude;
[JsonConstructor]
public Coord(JArray a){
this.longitude = (double)a[0];
this.latitude = (double)a[1];
}
}
}
Also, what is the best way to open such a large file in the main (assume it will be 100+ features) will streamreader be the best route?
Thank you

You can simplify your design quite a bit.
If you make your classes just plain ol' classes that represent your data:
public class Properties
{
public string Type { get; set; }
[JsonProperty(PropertyName = "R_STATEFP")]
public string RState { get; set; }
[JsonProperty(PropertyName = "L_STATEFP")]
public string LState { get; set; }
}
public class Geometry
{
public string Type { get; set; }
public List<List<double>> Coordinates { get; set; }
}
public class Feature
{
public string Type { get; set; }
public Properties Properties { get; set; }
public Geometry Geometry { get; set; }
}
public class RootObject
{
public string Type { get; set; }
public List<Feature> Features { get; set; }
}
You can then use JsonConvert.DeserializeObject<T>() to deserialize (and in the inverse JsonConvert.Serialize() to serialize).
RootObject rootObject = JsonConvert.DeserializeObject<RootObject>(jsonString);
You can see it in action here

Related

Using NetToplogySuite to get the geometry from Geojson file with method (IsWithinDistance) ASP.NET Core

I'm stuck in using NetTopologySuite with geojson file.
I want to get all the points from the geojson and then use the IsWithinDistance() method to get all the points within certain distance. I could deserialize the data and get the coordinates but the method doesn't work. I suppose that the method needs the points to be converted to WKB ? please correct me if I'm mistaken.
I could successfully execute the method when my first source of data stored in database but from json it doesn't work.
This is my controller :
public IActionResult GetWeather()
{
IList<WeatherViewModel> Tags = new List<WeatherViewModel>();
var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326);
var searchAreaCoordinate = new NetTopologySuite.Geometries.Coordinate(-1.882, 52.486);
var searchArea = geometryFactory.CreatePoint(searchAreaCoordinate);
Root weather = JsonConvert.DeserializeObject<Root>(System.IO.File.ReadAllText(#"C:\local\weatherx.json"));
var features = (from c in weather.features select c)
.Select(x=> new {x.id,x.type,x.geometry.coordinates})
// .Where(x=>x.Coor.IsWithinDistance(searchArea, 300))
.ToList();
;
foreach (var item in features)
{
Tags.Add(new WeatherViewModel()
{
id = item.id,
type = item.type,
Long = item.coordinates[0],
Lat = item.coordinates[1],
WKT = new NetTopologySuite.Geometries.Coordinate( item.coordinates[0] , item.coordinates[1])
}
);
}
return View(Tags);
}
Part of my json class:
public class Root
{
public string type { get; set; }
public ParameterDescription parameter_description { get; set; }
public List<double> bbox { get; set; }
public List<Feature> features { get; set; }
}
public class Geometry
{
public string type { get; set; }
public List<double> coordinates { get; set; }
}
public class Feature
{
public string id { get; set; }
public string type { get; set; }
public Properties properties { get; set; }
public Geometry geometry { get; set; }
public Geometry Coor {get;set;}
}
Here is part of my geojson:
{
"type": "FeatureCollection",
"features": [
{
"id": "1",
"type": "Feature",
"properties": {
"t": [
1,
],
"s": [
1,
],
"Time": [
"2021-11-01",
]
},
"geometry": {
"type": "Point",
"coordinates": [
-1.881,
52.486
]
}
},
]
}

Deserializing my JSON into POCO not populating few fields

I have below json which I need to deserialize in C# -
{
"clientSettings":[
{
"clientId":12345,
"entries":[
{
"key":"abc",
"value":false
},
{
"key":"def",
"value":false
},
{
"key":"ghi",
"value":false
}
]
},
{
"clientId":9876,
"entries":[
{
"key":"lkmn",
"value":false
}
]
}
],
"productSettings":[
{
"productId":11,
"entries":[
{
"key":"jkl",
"value":true
},
{
"key":"mno",
"value":true
}
]
},
{
"productId":12,
"entries":[
{
"key":"jkl",
"value":true
},
{
"key":"mno",
"value":true
}
]
}
],
"customerSettings":[
{
"key":"enableData",
"value":false
},
{
"key":"minPriceValue",
"value":"10.28"
},
{
"key":"presentData",
"value":"AEGIS"
}
],
"thothTest":{
"9876":[
"K"
],
"5431":[
"A",
"L"
],
"5123":[
"L"
]
},
"osirisTest":{
"7678":[
"K"
]
}
}
Below is the classes I created to deserialzie json into -
public class ProcessHolder : Holder
{
public IDictionary<int, ISet<string>> OsirisTest { get; set; }
public IDictionary<int, ISet<string>> ThothTest { get; set; }
}
public class Holder
{
public IList<Mapping> CustomerSettings { get; set; }
public IList<ClientSettingsMapping> ClientSettings { get; set; }
public IList<ProductSettingsMapping> ProductSettings { get; set; }
}
public class Mapping
{
public string Key { get; set; }
public object Value { get; set; }
}
public class ProductSettingsMapping : Mapping
{
public int ProductId { get; set; }
}
public class ClientSettingsMapping : Mapping
{
public int ClientId { get; set; }
}
I want to load all customerSettings values into CustomerSettings object of Holder class.
Similarly I want to load all clientSettings values into ClientSettings object of Holder class.
Similarly all productSettings values into ProductSettings object of Holder class.
Similarly thothTest values into ThothTest and osirisTest values into OsirisTest object.
I was trying with below code but somehow I am not able to see Key and Value variables being populated inside Mapping class object after deserializing my above json.
private static readonly JsonSerializerSettings serializerSettings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore
};
public static void Main(string[] args)
{
var jsonContent = File.ReadAllText("/beta/Downloads/test.json");
var config = JsonConvert.DeserializeObject<ProcessHolder>(jsonContent, serializerSettings);
if (config == null)
{
Console.WriteLine("Some Parsing Issue");
}
// using config object here
}
What is wrong I am doing here? I just need to deserialize my json into above classes and give me ProcessHolder object back which I can use later on.
Looking at your JSON, clientSettings and productSettings have entries array. There is no corresponding matching property in your class definition for same.
I would suggest to modify your class definition as per JSON. Try below and see if it helps:
public class ProductSettingsMapping
{
public int ProductId { get; set; }
public IList<Mapping> Entries { get; set; }
}
public class ClientSettingsMapping
{
public int ClientId { get; set; }
public IList<Mapping> Entries { get; set; }
}
Second option - if you are not able to modify classes, you can amend JSON. I am providing sample for clientSettings
{
"clientSettings": [
{
"clientId": 12345,
"key": "abc",
"value": false
},
{
"clientId": 12345,
"key": "def",
"value": false
},
{
"clientId": 12345,
"key": "ghi",
"value": false
},
{
"clientId": 9876,
"key": "lkmn",
"value": false
}
]
}
You can update productSettings accordingly.
Third option is to parse into JObject and then convert to your classes.
A sample for clientSettings
static void Main(string[] args)
{
var json = "{'clientSettings':[{'clientId':12345,'entries':[{'key':'abc','value':false},{'key':'def','value':false},{'key':'ghi','value':false}]},{'clientId':9876,'entries':[{'key':'lkmn','value':false}]}],'productSettings':[{'productId':11,'entries':[{'key':'jkl','value':true},{'key':'mno','value':true}]},{'productId':12,'entries':[{'key':'jkl','value':true},{'key':'mno','value':true}]}],'customerSettings':[{'key':'enableData','value':false},{'key':'minPriceValue','value':'10.28'},{'key':'presentData','value':'AEGIS'}],'thothTest':{'9876':['K'],'5431':['A','L'],'5123':['L']},'osirisTest':{'7678':['K']}}";
var parsed = JObject.Parse(json);
var parsedClientSettings = parsed["clientSettings"];
List<ClientSettingsMapping> clientSettings = new List<ClientSettingsMapping>();
foreach (var parsedClientSetting in parsedClientSettings)
{
var clientId = parsedClientSetting.Value<int>("clientId");
foreach (var entry in parsedClientSetting["entries"])
{
clientSettings.Add(new ClientSettingsMapping { ClientId = clientId, Key = entry["key"].ToString(), Value = entry["value"].ToString() });
}
}
ProcessHolder processHolder = new ProcessHolder() { ClientSettings = clientSettings };
Console.ReadLine();
}
You should define "entries" in both ProductSettingsMapping and ClientSettingsMapping class.
public class ProductSettingsMapping
{
public int ProductId { get; set; }
public IList<Mapping> entries { get; set; }
}
public class ClientSettingsMapping
{
public int ClientId { get; set; }
public IList<Mapping> entries { get; set; }
}

Deserializing Data From Facebook

I am using Unity and the Facebook SDK.
Currently I am retrieving a list of users friends who have the app installed using the graph API:
The data when it is returned looks as such:
{
"data": [
{
"installed": true,
"id": "1292282928282"
},
{
"installed": true,
"id": "29282829292"
}
],
"paging": {
"next": "https://graph.facebook.com/v2.5/105157539862931/friends?fields=installed&format=json&access_token=CAALVPHznNpcBAOnO94HvqUgYKI2kObPZBgR0sqIOMSRO9swZBBTWHb6FjliZCT1KyCmPbnX42xvtngboh3DjFOrixw0pSenwRZA1oXZAHNDdYcGsHNOHjQcZB0f6fsZBQJjhOTttwQu7E5hZBDcAWJVZBGK2AxrZBDZBxLL7I5pjXwwbb12hDytZAiVzUmNzi1Ae2CCvOnL6QCpqzsJT7fWWjXXi&limit=25&offset=25&__after_id=enc_AdB7PJbXYkDSSZAq33AjPXZAeRnlrZBDwjAAILZAg3emHdei0qdRLa2AeD6sRuX6h0OQuPQi8x8bvSHPy0EqIgybYL89"
},
"summary": {
"total_count": 2
}
}
Currently I am trying to figure out how I can extract the "Installed" and id from each object inside of the "data" object.
so far I am doing this:
Dictionary<object,object> friendsList = Json.Deserialize (result.RawResult) as Dictionary<object,object>;
But I am not sure how I can pull out these specific items from the objects.
Does anyone know how I would go about doing this?
You need to have classes that will hold the deserialized data for you. For example create the following classes:
public class Datum
{
public bool installed { get; set; }
public string id { get; set; }
}
public class Paging
{
public string next { get; set; }
}
public class Summary
{
public int total_count { get; set; }
}
public class RootObject
{
public List<Datum> data { get; set; }
public Paging paging { get; set; }
public Summary summary { get; set; }
}
RootObject is the root class so the deserialization code will be:
var deserialized = Json.Deserialize<RootObject>(result.RawResult);
There is one more way to do it without creating classes, by using the dynamic keyword:
static void Main(string[] args)
{
var stringVal = #"{
""data"": [
{
""installed"": true,
""id"": ""1292282928282""
},
{
""installed"": true,
""id"": ""29282829292""
}
],
""paging"": {
""next"": ""https://graph.facebook.com/v2.5/105157539862931/friends? fields=installed&format=json&access_token=CAALVPHznNpcBAOnO94HvqUgYKI2kObPZBgR0sqIOMSRO9swZBBTWHb6FjliZCT1KyCmPbnX42xvtngboh3DjFOrixw0pSenwRZA1oXZAHNDdYcGsHNOHjQcZB0f6fsZBQJjhOTttwQu7E5hZBDcAWJVZBGK2AxrZBDZBxLL7I5pjXwwbb12hDytZAiVzUmNzi1Ae2CCvOnL6QCpqzsJT7fWWjXXi&limit=25&offset=25&__after_id=enc_AdB7PJbXYkDSSZAq33AjPXZAeRnlrZBDwjAAILZAg3emHdei0qdRLa2AeD6sRuX6h0OQuPQi8x8bvSHPy0EqIgybYL89""
},
""summary"": {
""total_count"": 2
}
}";
dynamic x = JsonConvert.DeserializeObject(stringVal);
var data = x.data;
foreach(var d in data)
{
bool installed = d.installed;
long id = d.id;
// todo: use the id and installed
}
Run this in Linqpad and you it will return the installed property.
void Main()
{
string jsonText =
#"{
""data"": [
{
""installed"": true,
""id"": ""1292282928282""
},
{
""installed"": true,
""id"": ""29282829292""
}
],
""paging"": {
""next"": ""https://graph.facebook.com/v2.5/105157539862931/friends?fields=installed&format=json&access_token=CAALVPHznNpcBAOnO94HvqUgYKI2kObPZBgR0sqIOMSRO9swZBBTWHb6FjliZCT1KyCmPbnX42xvtngboh3DjFOrixw0pSenwRZA1oXZAHNDdYcGsHNOHjQcZB0f6fsZBQJjhOTttwQu7E5hZBDcAWJVZBGK2AxrZBDZBxLL7I5pjXwwbb12hDytZAiVzUmNzi1Ae2CCvOnL6QCpqzsJT7fWWjXXi&limit=25&offset=25&__after_id=enc_AdB7PJbXYkDSSZAq33AjPXZAeRnlrZBDwjAAILZAg3emHdei0qdRLa2AeD6sRuX6h0OQuPQi8x8bvSHPy0EqIgybYL89""
},
""summary"": {
""total_count"": 2
}
}";
var x = JsonConvert.DeserializeObject<Response>(jsonText);
//To Get installed
x.data.Select(d => d.installed).Dump();
}
public class Response
{
public Data[] data;
public Paging paging;
public Summary summary;
}
public class Data
{
public bool installed { get; set; }
public string id { get; set; }
}
public class Paging
{
public string next { get; set; }
}
public class Summary
{
public int total_count { get; set;}
}
Consults this example for obtain a friend list using mini json:https://developers.facebook.com/docs/unity/reference/current/Json

How do I get a property from a list when parsing JSON in C# with JSON.NET?

I'm able to parse simple properties using JSON.NET with this C# code:
Code C#
WebClient c = new WebClient();
var data = c.DownloadString("http://localhost/json1.json");
JObject o = JObject.Parse(data);
listBox1.Items.Add(o["name"]);
listBox1.Items.Add(o["email"][0]);
listBox1.Items.Add(o["email"][1]);
listBox1.Items.Add(o["website"]["blog"]);
json1.json
{
"name": "Fname Lname",
"email": [
"email#gmail.com",
"email#hotmail.com"
],
"website":
{
"blog": "example.com"
}
}
json2.json
{
"name": "Fname Lname",
"email": [
"email#gmail.com",
"email#hotmail.com"
],
"website":
{
"blog": "example.com"
},
"faculty":
{
"department": [
{
"name": "department.name",
"location": "department.location"
}
]
}
}
From the second JSON file, I'm not able to get name and location from the department. How do I do that in C#?
name : department.name
location: department.location
yourjsonobject.faculty.department[0].name;
yourjsonobject.faculty.department[0].location;
Here is some jsfiddle to help you with this:
http://jsfiddle.net/sCCrJ/
var r = JSON.parse('{"name": "Fname Lname","email": [ "email#gmail.com", "email#hotmail.com"],"website":{ "blog": "example.com"},"faculty":{ "department": [ { "name": "department.name", "location": "department.location" } ]}}');
alert(r.faculty.department[0].name);
alert(r.faculty.department[0].location);
for (var i = 0; i < r.faculty.department.length; i++) {
alert(r.faculty.department[i].name);
}
Your problem is that department is an array of objects (though it happens to just contain one item here), but you're not accessing it like it is. You can use o["faculty"]["department"][0]["name"] to get your data.
You might want to use classes (here are ones auto-converted with http://json2csharp.com/) to more easily work with your data.
public class Website
{
public string blog { get; set; }
}
public class Department
{
public string name { get; set; }
public string location { get; set; }
}
public class Faculty
{
public List<Department> department { get; set; }
}
public class RootObject
{
public string name { get; set; }
public List<string> email { get; set; }
public Website website { get; set; }
public Faculty faculty { get; set; }
}
Then you can get all of the data (instead of hoping the fixed indexes are right, and that you didn't make a typo in the property names) with this code:
WebClient c = new WebClient();
var data = c.DownloadString("http://localhost/json1.json");
var o = JsonConvert.DeserializeObject<RootObject>(data);
listBox1.Items.Add(o.name);
foreach (var emailAddr in o.email)
listBox1.Items.Add(emailAddr);
listBox1.Items.Add(o.website.blog);
foreach (var dept in o.faculty.department)
{
listBox1.Items.Add(dept.name);
listBox1.Items.Add(dept.location);
}

Newtonsoft JSON Deserialize AND jsonfreeze

I have a two simple PHP class
class Order{
public $orderNo;
public $lines = array();
public $paid = false;
public function addLine(OrderLine $line) {
$this->lines[] = $line;
}
public function setPaid($paid = true) {
$this->paid = true;
}
}
class OrderLine{
public function __construct($item, $amount){
$this->item = $item;
$this->amount = $amount;
}
public $item;
public $amount;
public $options;
}
Serialize object uses https://github.com/mindplay-dk/jsonfreeze
...
$json = new JsonSerializer;
$data = $json->serialize($order);
Have output:
{
"#type": "Order",
"orderNo": 123,
"lines": [{
"#type": "OrderLine",
"item": "milk \"fuzz\"",
"amount": 3,
"options": null
},{
"#type": "OrderLine",
"item": "cookies",
"amount": 7,
"options": {
"#type": "#hash",
"flavor": "chocolate",
"weight": "1\/2 lb"
}
}],
"paid": true
}
Send the string XMLRPC in VB.NET
As using Newtonsoft JSON get a live object?
As well as how to create a compatible format by analogy with the json string of living VB.net OR C# object?
Here's something you could start with. You create some classes with properties which represent the JSON Format (untested code, just as idea):
public class MyData
{
[JsonProperty("#type")]
public string Type { get; set; }
[JsonProperty("#orderNo")]
public int OrderNo { get; set;
[JsonProperty("paid")]
public bool Paid { get; set; }
[JsonProperty("lines")]
public List<MyDataLine> Lines { get; set; }
}
public class MyDataLines
{
[JsonProperty("#type")]
public string Type { get; set; }
[JsonProperty("options")]
public MyDataLinesOptions Options { get; set; }
// ... more
}
public class MyDataLinesOptions
{
// ... more
}
Then you can serialize and deserialize the the data like this:
string json = "the json data you received";
MyData myData = JsonConvert.DeserializeObject<MyData>(json);
// ...
json = JsonConvert.SerializeObject(myData);
"#type": "Order"
and
"#type": "OrderLine",
this is not a property, this is an indication of the type of the object

Categories