I have a Yaml file:
https://raw.githubusercontent.com/FortAwesome/Font-Awesome/master/src/icons.yml
And a class:
public class IconSearch
{
public string Name { get; set; }
public string ClassName { get; set; }
public IEnumerable<string> Filters { get; set; }
}
Can you tell me how I can deserialize the yaml to an IEnumerable of objects?
I expect something like this to work, but it returns null - I'm guessing it's because one of my properties is not the root node (icons). Instead, I'm trying to serialize the children of the root?
var input = new StringReader(reply);
var yaml = new YamlStream();
yaml.Load(input);
var icons = deserializer.Deserialize<IconSearch>(input);
The class you are trying to deserialize to seems to be missing properties.
I went the round about way of converting yaml to json to csharp and this is class that was generated:
public class Rootobject
{
public Icon[] icons { get; set; }
}
public class Icon
{
public string[] categories { get; set; }
public object created { get; set; }
public string[] filter { get; set; }
public string id { get; set; }
public string name { get; set; }
public string unicode { get; set; }
public string[] aliases { get; set; }
public string[] label { get; set; }
public string[] code { get; set; }
public string url { get; set; }
}
Resources used :
YAML to JSON online
JSON to CSHARP (I used Paste special in visual studio)
Use this to deserialize
var icons = deserializer.Deserialize<RootObject>(input);
Update
I have commented out the line that you use to create YamlStream as it is not required (it positions the reader to the end of the stream instead of the beginning, which would explain why you were getting null earlier). Your main method looks as follows and works. I have also fixed the bug that Antoine mentioned
public static void Main()
{
string filePath = "https://raw.githubusercontent.com/FortAwesome/Font-Awesome/master/src/icons.yml";
WebClient client = new WebClient();
string reply = client.DownloadString(filePath);
var input = new StringReader(reply);
//var yamlStream = new YamlStream();
//yamlStream.Load(input);
Deserializer deserializer = new Deserializer();
//var icons = deserializer.Deserialize<IconSearch>(input);
//Testing my own implementation
//if (icons == null)
// Console.WriteLine("Icons is null");
//Testing Shekhar's suggestion
var root = deserializer.Deserialize<Rootobject>(input);
if (root == null)
Console.WriteLine("Root is null");
}
Related
I want to edit GeoJson file, which I put part of its lines here. How to edit in this way, I have to read the file and change the Landuse value using the code in the properties.
{"type":"FeatureCollection", "features": [
{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[45.882982627281955,35.98144306876872],[45.8830448154499,35.98142063110326],[45.883106013386524,35.98143674855534],[45.883177395327635,35.981590195979166],[45.88306057502328,35.98161790966196],[45.882982627281955,35.98144306876872]]]},"properties":{"Code":1,"Landuse":"مسکونی","Longitude":45.8830793043,"latitude":35.9815185013}},
{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[45.88321822952168,35.98143433703011],[45.88329577844585,35.981578778123584],[45.883184747057655,35.98160599975271],[45.883177395327635,35.981590195979166],[45.88313701140243,35.981503383976175],[45.883107851319025,35.981440699498734],[45.88321822952168,35.98143433703011]]]},"properties":{"Code":2,"Landuse":"مسکونی","Longitude":45.8832014571,"latitude":35.9815182472}},
...
]}
I converted the GeoJson file to C# classes using this site.
And the result is as follows
public class ConvertorJsonLayerDTO {
public class Feature {
public string type {
get;
set;
}
public Geometry geometry {
get;
set;
}
public Properties properties {
get;
set;
}
}
public class Geometry {
public string type {
get;
set;
}
public List<List<List<double>>> coordinates {
get;
set;
}
}
public class Properties {
public int Code {
get;
set;
}
public string Landuse {
get;
set;
}
public double Longitude {
get;
set;
}
public double latitude {
get;
set;
}
}
public class Root {
public string type {
get;
set;
}
public List<Feature>features {
get;
set;
}
}
}
Now I read the file in C# as follows:
var code = 2;
var Geojson = File.ReadAllText(Path);
var deserialize = JsonConvert.DeserializeObject<Root>(Geojson);
Now, how do I make a blind move on this file and change the property whose code is 2 to the Landuse property value and update the file?
Please guide me. I will definitely share the result with you...Thankful
I'd recomend using Linq:
var feature = deserialize.features.FirstOrDefault(feature => feature.properties.Code == 2);
if (feature != null)
{
feature.properties.Landuse = "new Landuse";
}
It gives you the first feature where feature.properties.Code is equal to 2 or it returns null if there is no feature with the code 2.
You could Try with JObject to avoid unnecessary models/Properties for rest part of your file
var str= System.IO.File.ReadAllText("path");
var jobj= JObject.Parse(str);
var newjobj= (JObject)jobj["SomeSection"]["ChildSection"];
var obj = newjobj.ToObject<TargetObject>();
enter image description here
I did the same but got this error
I'm just looking for a solution to query a GeoJson file and edit the desired value and save it again.
This is my first question on SO, please let me know if I am doing anything wrong!
I am trying to parse an XML similar to this:
<LiveUpdate>
<CityID>F0A21EA2</CityID>
<CityName>CityTown</CityName>
<UserName>john</UserName>
<ApplicationDetails>
<ApplicationDetail
Application="AC"
Licensed="true"
Version="2015.2"
Patch="0001"
/>
<ApplicationDetail
Application="AP"
Licensed="true"
Version="2015.2"
Patch="0002"
/>
</ApplicationDetails>
</LiveUpdate>
I have classes that look like this:
public class Client
{
public string cityID { get; set; }
public string cityName { get; set; }
public string userName { get; set; }
public List<Apps> appList { get; set; }
}
public class Apps
{
public string app { get; set; }
public string licensed { get; set; }
public string version { get; set; }
public string patch { get; set; }
}
I need to be able to have a client class with a list of all the application details to be iterated over.
So far the best I've come up with is:
XDocument xml = XDocument.Load(#"C:\blah\Desktop\1.xml");
var liveUpdate = xml.Root;
var clients = (from e in liveUpdate.Elements()
select new Client()
{
cityID = e.Element("CityID").Value,
cityName = e.Element("CityName").Value,
userName = e.Element("UserName").Value,
appList = e.Elements("ApplicationDetails")
.Select(a => new Apps()
{
app = a.Element("Application").Value,
licensed = a.Element("Licensed").Value,
version = a.Element("Version").Value,
patch = a.Element("Patch").Value
}).ToList()
});
However, I'm currently running into an error that says Object reference not set to an instance of an object.
I've seen some similar examples on here, but not that deal with data before the multiple children.
I'm fairly new to XML and Linq so any help here would be greatly appreciated!
Your XML only contains one LiveUpdate tag, so rather than iterating over all of the elements inside of it, you just want to look at the Root element.
In ApplicationDetails, Application, Licensed and such are attributes, not elements. Use .Attribute() to access them.
ApplicationDetails is a single tag, and inside it you have ApplicationDetail tags.
There is no DateTime element in your LiveUpdate tag.
This works:
var liveUpdate = xml.Root;
var e = liveUpdate;
var clients = new Client()
{
cityID = e.Element("CityID").Value,
cityName = e.Element("CityName").Value,
userName = e.Element("UserName").Value,
//dateTime = e.Element("DateTime").Value,
appList = e.Element("ApplicationDetails").Elements("ApplicationDetail")
.Select(a => new Apps()
{
app = a.Attribute("Application").Value,
licensed = a.Attribute("Licensed").Value,
version = a.Attribute("Version").Value,
patch = a.Attribute("Patch").Value
}).ToList()
};
Since you have already defined a class into which you wish to deserialize, you can use XmlSerializer to deserialize it for you.
First, let's rename some of your property names to more closely match the XML and c# naming conventions:
[XmlRoot("LiveUpdate")]
public class Client
{
public string CityID { get; set; }
public string CityName { get; set; }
public string UserName { get; set; }
[XmlArray("ApplicationDetails")]
[XmlArrayItem("ApplicationDetail")]
public List<Apps> AppList { get; set; }
}
public class Apps
{
[XmlAttribute]
public string Application { get; set; }
[XmlAttribute]
public bool Licensed { get; set; }
[XmlAttribute]
public string Version { get; set; }
[XmlAttribute]
public string Patch { get; set; }
}
Then add the following extension methods:
public static class XmlSerializationHelper
{
public static T LoadFromXML<T>(this string xmlString)
{
using (StringReader reader = new StringReader(xmlString))
{
object result = new XmlSerializer(typeof(T)).Deserialize(reader);
if (result is T)
{
return (T)result;
}
}
return default(T);
}
public static T LoadFromFile<T>(string filename)
{
using (var fs = new FileStream(filename, FileMode.Open))
{
object result = new XmlSerializer(typeof(T)).Deserialize(fs);
if (result is T)
{
return (T)result;
}
}
return default(T);
}
}
Now you can deserialize from your XML file as follows:
string fileName = #"C:\blah\Desktop\1.xml";
var client = XmlSerializationHelper.LoadFromFile<Client>(fileName);
I manually updated your Client class to map correctly to the provided XML, but if you wanted to do it automatically, see here: Generate C# class from XML.
I have seen some other questions like this, but those are quite complex JSON data's that have objects within objects. Although the JSON I'm working with is never static, I doubt it's as complex as those. Also, it's my first time using JSON with C# so I'm a little clueless.
What I'm trying to achieve is to separate the data that is received from an API that I prompt using WebRequest in C#.
{
"johhny.debt": {
"id":35187540,
"name":"johnny.debt",
"profileIconId":786,
"Level":30,
"revisionDate":1428019045000
}
}
The returned JSON data is in a fashion like thereof.
I want to be able to access all of the properties of the above string in the following manner:
ID :
Name:
~~
~~
~~
... and so forth.
I'm assuming some type of class has to be made for this?
All help is appreciated, thank you all in advance.
Install Json.Net from Nuget
Install-Package Newtonsoft.Json
https://www.nuget.org/packages/Newtonsoft.Json/
Declare class for inner object ({"id":..., "name": ... }):
public class InnerObject
{
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("name")]
public string Username { get; set; }
[JsonProperty("profileIconId")]
public int ProfileIconId { get; set; }
[JsonProperty("level")]
public int Level { get; set; }
[JsonProperty("revisionDate")]
public string RevisionDate { get; set; }
}
As you can see you can specify rename mapping from json fields to .Net object properties using JsonPropertyAttribute.
Read your json to Dictionary<string,InnerObject> and get value of "johhny.debt" key:
var dict = JsonConvert.DeserializeObject<Dictionary<string, InnerObject>>(jsonText);
var johhny = dict["johhny.debt"];
Or if your need always to parse exact json property 'johhny.debt', you could create root object class:
public class RootObject
{
[JsonProperty("johhny.debt")]
public InnerObject JohhnyDept { get; set; }
}
And deserialize it:
var root = JsonConvert.DeserializeObject<RootObject>(jsonText);
var johhny = root.JohhnyDebt;
Just Create a class like this
public class RootObject
{
public int Id { get; set; }
public string name { get; set; }
public int profileIconId { get; set; }
public int Level { get; set; }
public string revisionDate { get; set; }
}
then install json.Net and this code to your main method
var jsonObject=JsonConvert.DeserializeObject<RootObject>(jsonText);
That's all
Update
var obj = JObject.Parse(json);
var RootObject = new RootObject()
{
Id = (int)obj["johhny.debt"]["id"],
Level = (int)obj["johhny.debt"]["Level"],
name = (string)obj["johhny.debt"]["name"],
profileIconId = (int)obj["johhny.debt"]["profileIconId"],
revisionDate = (string)obj["johhny.debt"]["revisionDate"]
};
I have created a little logg program and with this i can save custom classes to xml, and convert them back from xml to a class. this works fine, but the problem is if i want to add one class to the list in the xml, i have to read all of them, add one class and rewrite all of them if i use this method, now i know i can manualy add a class by searching for elements and so on, but i wondered if i could do this in the way that i write all of them.
this is an example of the code that i ame using:
public static void Test()
{
List<LoggInformation> infos = new List<LoggInformation>();
infos.Add(new LoggInformation() { Level = BpuInterface.BpuInterface.BPUController.LoggLevel.Debug, Message = "error1" });
infos.Add(new LoggInformation() { Level = BpuInterface.BpuInterface.BPUController.LoggLevel.Error, Message = "error2" });
DataContractSerializer dd = new DataContractSerializer(typeof(List<LoggInformation>));
using (var writer = new StreamWriter(#"C://testLoggfile.xml"))
{
dd.WriteObject(writer.BaseStream, infos);
}
}
public static void AddOneItem()
{
//??????????
}
[DataContract]
public class LoggInformation
{
[DataMemberAttribute]
public BpuInterface.BpuInterface.BPUController.LoggLevel Level { get; set; }
[DataMemberAttribute]
public Source Source { get; set; }
[DataMemberAttribute]
public string ExceptionMessage { get; set; }
[DataMemberAttribute]
public string ExceptionStack { get; set; }
[DataMemberAttribute]
public string ThreadName { get; set; }
[DataMemberAttribute]
public System.Threading.ApartmentState ThreadApartmentState { get; set; }
[DataMemberAttribute]
public string Message { get; set; }
[DataMemberAttribute]
public DateTime DateTime { get; set; }
}
You can use this instead new StreamWriter(#"C://testLoggfile.xml"), true) will append line at the end of file.
public static void Test()
{
...
using (var writer = new StreamWriter(#"C://testLoggfile.xml"), true) // this will append line at the end of file.
{
dd.WriteObject(writer.BaseStream, infos);
}
}
...
For Windows 8 application development environment.
Code:
var deserialized = JsonConvert.DeserializeObject<RootObject>(json);
listView.ItemsSource = deserialized; // error
Data model:
public class C
{
public List<Y> programs { get; set; }
public string name { get; set; }
public int code { get; set; }
}
public class RootObject
{
public List<C> cs { get; set; }
public string date { get; set; }
}
public class Y
{
public string category { get; set; }
public string time { get; set; }
public string name { get; set; }
}
What can I do ? I don't find solution.
ItemsSource is looking for an IEnumerable, but you're providing a single object in RootObject. You'd get the same error if you create one of your RootObject instances in code and try the same assignment.
What specifically should be displaying in the list? If you simply change your code to:
listView.ItemsSource = deserialized.cs;
the listView should display your C objects.
I always have trouble figuring out how to go from the serializer output. I do have working code (windows 8 store) that I'm pasting below. It is pretty obvious what it does.
HttpResponseMessage responseGetEmailByPersonsBare =
await clientGetEmailByPersonsBare.PostAsync(UrlBase + EmailDetailGetEmailByPersonsBare, contentGetEmailByPersonsBare);
Stream myStream = await responseGetEmailByPersonsBare.Content.ReadAsStreamAsync();
var djsGetEmailByPersonsBare = new DataContractJsonSerializer(typeof(AEWebDataStructures.RootObjectEmailDetail));
var rootObjectEmailDetail = (AEWebDataStructures.RootObjectEmailDetail)djsGetEmailByPersonsBare.ReadObject(myStream);
responseGetEmailByPersonsBare.EnsureSuccessStatusCode();
returnTaskInfo.EmailDetails = rootObjectEmailDetail.Data;
returnTaskInfo.StatusReturn = AEWebDataStructures.StatusReturn.Success;