I want to read files, each of which contains a person's details, as below, and convert it to a Person object.
Covert below
id=1
firstName=John
lastName=Smith
To:
public class Person
{
public int Id {get;set;}
public string FirstName{get;set;}
public string LastName{get;set;}
}
Are there .NET built-in methods to do that, or third party library. I cannot find it via google.
Update:
The file format CANNOT be changed.
.NET is really into XML, so you won't find build-in functionality for INI-like formats. But there are a bunch of libs that make it easy to read and write such files, e.g. ini-parser or nini, but you still have to do the mapping to and from objects manually.
You could parse the text with String.Split and LINQ:
Dictionary<string, string> dict = text
.Split(new[] { Environment.NewLine }, StringSplitOptions.None)
.Select(e => e.Split('='))
.ToDictionary(strings => strings[0], strings => strings[1]);
Then use something like Dictionary Adapter.
For example using File.ReadAllLines, a little bit of Linq and String.Substring?
var lines = File.ReadAllLines(path).Select(l => l.Trim());
var idLine = lines.FirstOrDefault(l => l.StartsWith("id=", StringComparison.OrdinalIgnoreCase));
var lNameLine = lines.FirstOrDefault(l => l.StartsWith("lastname=", StringComparison.OrdinalIgnoreCase));
var fNameLine = lines.FirstOrDefault(l => l.StartsWith("firstname=", StringComparison.OrdinalIgnoreCase));
if (idLine != null && lNameLine != null && fNameLine != null)
{
Person person = new Person()
{
Id = int.Parse(idLine.Substring(idLine.IndexOf("=") + 1)),
FirstName = fNameLine.Substring(fNameLine.IndexOf("=") + 1),
LastName = lNameLine.Substring(lNameLine.IndexOf("=") + 1)
};
}
(assuming that there's just one person per file)
But i would use a different format like XML (or a database of course).
I really think you should consider changing your input data format into something more standard (like XML or JSON).
But that does not mean you can't read your file at all. You should just read your text file by your own:
var people = new List<Person>();
using (var stream = File.OpenRead("Input.txt"))
{
using (var reader = new StreamReader(stream))
{
while (!reader.EndOfStream)
{
int id = int.Parse(reader.ReadLine().Substring(3));
string firstName = reader.ReadLine().Substring(10);
string lastName = reader.ReadLine().Substring(9);
var newPerson = new Person()
{
Id = id,
FirstName = firstName,
LastName = lastName
};
people.Add(newPerson);
}
}
}
If you have the data in a format like this:
<Person>
<Id>1</Id>
<FirstName>John</FirstName>
<LastName>Smith</LastName>
</Person>
Then this C# code will desrialise into an instance of Person
//assuming you have a string called "data" that contains the above XML.
XDocument xd=XDocument.Parse(data); //needs System.Xml.Linq for XDocument type.
using(var reader = xd.CreateReader())
{
using(XmlSerializer ser = new XmlSerializer(typeof(Person))
{
Person p = ser.Deserialize(reader) as Person;
//p will be null if it didn't work, so make sure to check it!
}
}
Note that the deserializer is case sensitive so you need to make sure the element cases match the casing of the properties in your class (You can get arond this by decorating your properties with Serializer attributes that tell the serialzer how to map them here)
The plain native serialzer is great for simple objects like this but can trip you up on some data types like char, bool, etc, so do checkout that link on the attributes.
If you wanted to do it from the format you gave in the question, you'd need to write a custom serialiser, in your case my advice would be to read from your file and generate XML from the data using XDocument Hope that helps.
Related
How can find out result of this:
<People>
<Person name="John" />
<Person name="Andrew" />
</People>
I need to find out if person with specific name exists in People list.
Example:
if (Element("People").ForAny(person => person.name == "John")) // Returns True
if (Element("People").ForAny(person => person.name == "Amanda")) // Returns False
I am using Xml Linq library.
Thanks for any help!
You need to work on your separation of concerns: divide your problems into smaller problems that can be used independently. This make it easier to reuse your code for other problems, easier to test your code, make changes without breaking the code.
Your problem consists of two subproblems:
How to convert XML data to a sequence of Persons
How to extract Persons with a certain name from a sequence of Persons
How to detect if a sequence of Persons is not empty?
I don't often convert XML to IEnumerable, but this answer helped me.
class Person
{
public string Name {get; set;}
... // other properties
}
If in your XML a Person really only has a Name, you don't have to define a special class for it. But then again: are you sure that a Person is nothing more than a Name? Shouldn't that be a collection of Names?
Ok, so we have a Person class (or a string), and we need a function to convert the XML into a sequence of Persons:
Write this as an extension method, so we can let it look like LINQ. See extension methods demystified. The word this in the signature makes it an extension method. It allows you to use the method as if it was a method of the string class itself
public static IEnumerable<Person> ToPersons(this String xml)
{
return XElement.Parse(xml)
.Elements("Person")
.Select(xmlElement => new Person
{
Name = xmlElement.Element("Name").Value,
// if needed, fill other properties, for instance:
Id = Int32.Parse(xmlElement.Element("Id").Value),
});
}
Usage:
string xmlTxt = ...
IEnumerable<Person> persons = xmlTxt.ToPersons();
If you don't have a string with xml, but an XmlReader, consider:
public static IEnumerable<Person> ToPersons(this XmlReader xmlReader)
{
while(xmlReader.Read())
{
// TODO: read one Person from xmlReader
Person person = new Person() {...} // you know better how to do this than I
yield return person
}
Now that we have seperated xml conversion from Person handling, the rest is easy:
Requirement:
Given the name of a Person, and some XmlText that represents a sequence of Persons, tell me if a Person with this name is in this sequence
string personName = ...
string xmlText = ... // or Use the XmlReader
bool personAvailable = xmlText.ToPersons()
.Where(person => person.Name == personName)
.Any();
In words: convert the xmlText to a sequence of Persons. From this sequence keep only those Persons that have a Name equal to personName. Return true if there is any element left in the remaining sequence.
If you use peculiar characters, or want to ignore case. Consider:
IEqualityComparer<strong> personNameComparer = StringComparer.CurrentCultureIgnoreCase;
bool personAvailable = xmlText.ToPersons()
.Where(person => personNameComparer.Equals(person.Name, personName))
.Any();
The nice thing is, because you separated your concerns, you can use ToPersons also for other functions:
Requirement: give me all New York City Residents, born before 1960
var oldPersons = xmlText.ToPersons
.Where(person => person.Location == "New York City" && person.Birthday.Year < 1960);
Or if you get your Persons from a Json file, or a CSV-file, or a database, you can still get all all New York City Residents, born before 1960, while only writing a new ToPersons method.
You can simply navigate from the root element People.
In all its decendants Person, is there any with the attribute name is equal to the value you are looking for :
string input = #"<People>
<Person name=""John"" />
<Person name=""Andrew"" />
</People>";
XDocument doc = XDocument.Parse(input);
var isJohnHere = doc.Element("People")
.Descendants("Person")
.Any(x=> x.Attribute("name").Value == "John");
The same way getting the List<string> of people's names will be :
var names = doc.Element("People")
.Descendants("Person")
.Select(x=> x.Attribute("name").Value);
And even shorter " All the Persons no matter where there are" :
var isJohnHere2 = doc.Descendants("Person")
.Any(x=> x.Attribute("name").Value == "John");
Live demo
I read json values from a text and store it in array using this code.
string[] allLines = System.IO.File.ReadAllLines("D:\\tweets.txt");
I need to extract certain fields from this array containing Json.
My Json is of this type:
{"Name":"John","Id":"45","Time":"11 pm"}
{"Name":"Pear","Id":"34","Time":"3 pm"}
I want to extract each "Name" in one array and each "Id" in one array, something like this.
string[] Name= null;
string[] Id= null;
for (var i = 0; i < allLines[i].length; i++)
{
Name = allLines[i].Name;
Id = allLines[i].Id;
}
I tried another way using json parsing as well. I can obtain one row at one time json deserialized this way. But then confused how to obtain the selected fields.
StreamReader streamReader = System.IO.File.OpenText("D:\\tweets.txt");
string lineContent = streamReader.ReadLine();
do
{
if (lineContent != null)
{
var a = JsonConvert.DeserializeObject(lineContent);
}
lineContent = streamReader.ReadLine();
}
while (streamReader.Peek() != -1);
streamReader.Close();
Please help.
I recommend using Json.NET to parse JSON, you can download it as a NuGet package.
It has some great documentation about querying JSON here
Querying your JSON with LINQ would look something like:
JObject json = JObject.Parse(json);
var name = from p in json
select (string)p["Name"];
This example uses the NewtonSoft Json library to deserialize your Json into an object. Then, linq is used to pull out the lists that you are interested in.
I have written this example as a Console Application in Visual Studio. You will need to create a new Console Application, then copy this code into it.
Also, to use the NewtonSoft library in your new Console Application, you will need to load it from NuGet. To do this in VisualStudio, you will need to
Right-click on the project name
Click on Manage NuGet Packages...
In the search box on the top right, enter "newtonsoft" (without the quotes)
Newtonsoft.Json should show up in the list. Click it and press the Install button. This will load the binary and set up the references in your project. After that, you can use the sample code shown in this example.
static void Main(string[] args)
{
TestParseJson();
Console.WriteLine();
Console.WriteLine("Press Any Key to End");
Console.ReadLine(); // Wait for input so we can see our output text
}
// 1 - Construct an object used for deserialization. You will need to make this class match the format of the records in your json text file.
public class User
{
public string Name { get; set; }
public int Id { get; set; }
public DateTime Time { get; set; }
}
// 2 - Simulate Json creation and then use the NewtonSoft library to deserialize. You will need to just extract from the DeserializeObject line down
public static void TestParseJson()
{
// Read list of json objects from file, one line at a time. The json in the test file users.json is in this format:
// {"Name":"John","Id":45,"Time":"2015-11-05T19:18:02.0324468Z"}
// {"Name":"Pear","Id":34,"Time":"2015-11-06T19:18:02.0329474Z"}
var jsonLines = File.ReadLines(#"c:\temp\users.json");
var deserializedUsers = jsonLines.Select(JsonConvert.DeserializeObject<User>).ToList();
// Use Linq to project the list of deserializedUsers into the lists that you want
var names = deserializedUsers.Select(user => user.Name);
var ids = deserializedUsers.Select(user => user.Id);
// Output list of names and ids for debugging purposes
Console.WriteLine("");
Console.WriteLine(" Names:");
foreach (var name in names)
{
Console.WriteLine(" " + name);
}
Console.WriteLine(" Ids:");
foreach (var id in ids)
{
Console.WriteLine(" " + id);
}
}
Your JSON does not actually represent an array, but rather a series of individual objects back-to-back. To be considered a valid JSON array, the objects would need to be enclosed in square brackets and separated by commas (see JSON.org). Regardless, it is still possible to read and parse this non-standard JSON using Json.Net. The JsonTextReader class has a special SupportMultipleContent setting that is designed to cope with this situation. You can process your file using the following code:
List<string> names = new List<string>();
List<string> ids = new List<string>();
JsonSerializer serializer = new JsonSerializer();
using (StreamReader sr = new StreamReader("D:\\tweets.txt"))
using (JsonTextReader reader = new JsonTextReader(sr))
{
reader.SupportMultipleContent = true;
while (reader.Read())
{
if (reader.TokenType == JsonToken.StartObject)
{
JObject jo = JObject.Load(reader);
names.Add((string)jo["Name"]);
ids.Add((string)jo["Id"]);
}
}
}
Console.WriteLine("Names: " + string.Join(", ", names));
Console.WriteLine("Ids: " + string.Join(", ", ids));
Fiddle: https://dotnetfiddle.net/tYVLLr
Ok, I have a small issue reading one of my company's notorious malformed xml files.
Trying to get 5 values from it and save them individually as variables.
Here is an example of the tricky XML.
(I may not be using the right terms, but I couldn't find anything on reading values of this type)
<ONE>
<TWO>
<THREE>
</THREE>
</TWO>
<DATA internalid="1" externalid="2" lastname="lname" firstname="name" date="20.03.2003"/>
</ONE>
So, the data I need is internalid, externalid, lastname, firstname, and date.
What I've been working with so far, and unable to make anything happen.
string xml = (#"C:\1.xml");
var xmlElement = XElement.Load(xml);
var xmlList = (from message in xmlElement.Elements("DATA")
select new
{
internalid = message.Attribute("internalid").Value,
externalid = message.Attribute("externalid").Value,
lastname = message.Attribute("lastname").Value,
firstname = message.Attribute("firstname").Value,
date = message.Attribute("date").Value
}).ToString();
And I'm unable to get it to fly. Not that I'm getting any errors, but when I out this string to a richtextbox or just textbox I get this....
System.Linq.Enumerable+WhereSelectEnumerableIterator2[System.Xml.Linq.XElement,<>f__AnonymousType05[System.String,System.String,System.String,System.String,System.String]]
Also, so I can better research the problem, what is it called when data is INSIDE the tag like that?
Thanks guys!
As #Jon Skeet mentioned you are calling ToString() on a sequence. The following code may get your closer to your desired solution.
var xmlList = (from message in xmlElement.Elements("DATA")
select new
{
internalid = message.Attribute("internalid").Value,
externalid = message.Attribute("externalid").Value,
lastname = message.Attribute("lastname").Value,
firstname = message.Attribute("firstname").Value,
date = message.Attribute("date").Value
});
StringBuilder builder = new StringBuilder();
foreach (var item in xmlList)
{
builder.Append(item);
}
string test = builder.ToString();
As for your question regarding "data is INSIDE the tag like that". These are examples of XML Attributes.
Here's a good resource to start learning linq Introduction to LINQ Queries (C#).
There's nothing wrong with how you've read the data and saved to variables. To display your data, instead of trying to convert the xmlList object to a string, just iterate through your list to output your data.
string xml = (#"C:\1.xml");
var xmlElement = XElement.Load(xml);
var xmlList = (from message in xmlElement.Elements("DATA")
select new
{
internalid = message.Attribute("internalid").Value,
externalid = message.Attribute("externalid").Value,
lastname = message.Attribute("lastname").Value,
firstname = message.Attribute("firstname").Value,
date = message.Attribute("date").Value
});
StringBuilder outputString = new StringBuilder();
foreach (var xmlRecord in xmlList)
{
string outputRecord =
string.Format("internalid: {0}, externalid: {1}, lastname: {2}, firstname: {3}, date: {4}",
xmlRecord.internalid.ToString(), xmlRecord.externalid.ToString(),
xmlRecord.lastname.ToString(), xmlRecord.firstname.ToString(),
xmlRecord.date.ToString());
outputString.AppendLine(outputRecord);
}
Console.WriteLine(outputString.ToString());
Console.ReadLine();
i'm coming from PHP to C#, so please excuse some of my terminology.
Currently i'm working on a small project that requires multiple profiles to be stored in one single file, so i decided to use XML, because INI files (usually my go to guy for text based stuff) are not really supported by C#. At least not in a satisfying way.
Here the basic structure of my XML file:
<profile name="FooBar">
<btnA pressed="actionA" released="actionB" />
<btnB pressed="actionX" released="actionY" />
...
</profile>
<profile name="XYZ">
<btnA pressed="actionA" released="actionB" />
<btnB pressed="actionX" released="actionY" />
...
</profile>
In PHP i would generate an associative array with the following structure:
<?php
foo = array(
'FooBar' => array(
'btnA_pressed' => 'actionA',
'btnA_released' => 'actionB'
// ...
),
'XYZ' => array(
// ...
)
);
EDIT START
Application Class Structure:
Settings (Contains all profiles and a reference to the current profile)
Profile (See below)
The Profile class:
public class Profile
{
private string _name;
public string Name
{
get { return this._name; }
set { this._name = value;}
}
private string _btnA_pressed;
public string BtnA_Pressed { get; set; }
// and so on...
public Profile(var data) { // arg is a placeholder
// associate the data with the properties
}
}
In short, the Settings class holds all profiles and a reference to the selected profile. Access to the profile goes over Settings.CurrentProfile.propertie_Name()
EDIT END
The question is now, how do i achieve the same or a similar thing in C#? Or are there better methods of achieving the same thing?
Thanks for your help in advance!
XML structures can be manipulated very easily with LINQ2XML without the need of typed models (classes).
Reading XML file containing many profile nodes (and i assume your XML file is correct and has one root node), can look like this:
// read existing XML structure
var xml = XDocument.Load("d:\\temp\\xml\\profile.xml");
// take all profile elements
var profiles = xml.Root.Elements("profile").ToList();
foreach (var profile in profiles)
{
Console.WriteLine(profile.Attribute("name").Value);
// find all button elements
var buttons = profile
.Elements()
.Where (e => e.Name.ToString().StartsWith("btn"));
// list elements
foreach (var button in buttons)
{
// tag name
var name = button.Name.ToString();
// attributes
var pressed = button.Attribute("pressed").Value;
var released = button.Attribute("released").Value;
Console.WriteLine(String.Format("{0} - P'{1}' - R'{2}'", name, pressed, released));
}
}
The output is:
FooBar
btnA - P'actionA' - R'actionB'
btnB - P'actionX' - R'actionY'
XYZ
btnA - P'actionA' - R'actionB'
btnB - P'actionX' - R'actionY'
Reading a single profile XML structure from a string and then creating a new one can look like this:
var xmlCode = #"<profile name=""FooBar""><btnA pressed=""actionA"" released=""actionB"" /><btnB pressed=""actionX"" released=""actionY"" /></profile>";
try
{
// read existing XML structure
var xml = XDocument.Parse(xmlCode); // XDocument.Load("c:\\path\\to\\file.xml");
// find all button elements
var buttons = xml.Root
.Elements()
.Where (e => e.Name.ToString().StartsWith("btn"));
// list elements
foreach (var button in buttons)
{
// tag name
var name = button.Name.ToString();
// attributes
var pressed = button.Attribute("pressed").Value;
var released = button.Attribute("released").Value;
Console.WriteLine(String.Format("{0} - P'{1}' - R'{2}'", name, pressed, released));
}
// create xml
// root element
var newXml = new XElement("profile", new XAttribute("name", "FooBaz"),
new XElement("btnA",
new XAttribute("pressed", "actionX"),
new XAttribute("released", "actionXR")),
new XElement("btnB",
new XAttribute("pressed", "actionZ"),
new XAttribute("released", "actionZR")));
Console.WriteLine(newXml.ToString());
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
}
The output is:
btnA - P'actionA' - R'actionB'
btnB - P'actionX' - R'actionY'
<profile name="FooBaz">
<btnA pressed="actionX" released="actionXR" />
<btnB pressed="actionZ" released="actionZR" />
</profile>
You can use LINQ2XML to read the data and fill a list of objects of your Profile type like this:
// read existing XML structure
var xml = XDocument.Load("d:\\temp\\xml\\profile.xml");
// take all profile elements
var profiles = xml.Root.Elements("profile").ToList();
var listOfProfiles = new List<Profile>();
foreach (var profile in profiles)
{
var profileObject = new Profile("");
profileObject.Name = profile.Attribute("name").Value;
// find all button elements
var buttons = profile
.Elements()
.Where (e => e.Name.ToString().StartsWith("btn"));
// list elements
foreach (var button in buttons)
{
// attributes
var pressed = button.Attribute("pressed").Value;
var released = button.Attribute("released").Value;
profileObject.BtnA_Pressed = pressed;
}
listOfProfiles.Add(profileObject);
}
You can also use XML serialization - you need to describe your XML structure as a class (typed model) and deserialize (read XML file into your class) resp. serialize (write your XML structure to a file). A generic implementation of the methods for serialization resp. deserialization can look like this:
public void SerializeModel<T>(string fqfn, T entity)
{
var xmls = new XmlSerializer(entity.GetType());
var writer = new StreamWriter(fqfn);
xmls.Serialize(writer, entity);
writer.Close();
}
public T DeserializeModel<T>(string fqfn)
{
var fs = new FileStream(fqfn, FileMode.Open);
var xmls = new XmlSerializer(typeof(T));
var r = (T) xmls.Deserialize(fs);
fs.Close();
return r;
}
The typed model that describes your Profile class and the lists contained within, looks like this (note the usage of the different XML serialization attributes):
public class Profiles
{
[XmlElement(ElementName="Profile")]
public List<Profile> Profile { get; set; }
}
public class Profile
{
[XmlArray(ElementName="Buttons")]
public List<Button> Buttons { get; set; }
[XmlAttribute]
public String Name;
}
public class Button
{
[XmlAttribute]
public String Pressed { get; set; }
[XmlAttribute]
public String Released;
}
Creation of an XML file:
var profiles = new Profiles();
var profileA = new Profile();
var profileB = new Profile();
var buttonA = new Button();
var buttonB = new Button();
profileA.Buttons = new List<Button>();
profileB.Buttons = new List<Button>();
profiles.Profile = new List<Profile>();
profileA.Name = "Profile A";
profileB.Name = "Profile B";
buttonA.Pressed = "Pressed A";
buttonA.Released = "Release A";
buttonB.Pressed = "Pressed B";
buttonB.Released = "Release B";
profileA.Buttons.Add(buttonA);
profileB.Buttons.Add(buttonB);
profiles.Profile.Add(profileA);
profiles.Profile.Add(profileB);
var xmlFile = "d:\\temp\\xml\\profile_model.xml";
SerializeModel<Profiles>(xmlFile, profiles);
The new XML file looks like this (note, the structure was slightly modified because of the way XML serialization in .NET handles arrays/lists):
<?xml version="1.0" encoding="utf-8"?>
<Profiles xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Profile Name="Profile A">
<Buttons>
<Button Released="Release A" Pressed="Pressed A" />
</Buttons>
</Profile>
<Profile Name="Profile B">
<Buttons>
<Button Released="Release B" Pressed="Pressed B" />
</Buttons>
</Profile>
</Profiles>
The file can be then read like this:
var input = DeserializeModel<Profiles>(xmlFile);
foreach (var profile in input.Profile)
{
var b = profile.Buttons.First();
Console.WriteLine(String.Format("{0} - {1} - {2}", profile.Name, b.Pressed, b.Released));
}
The output is as expected:
Profile A - Pressed A - Release A
Profile B - Pressed B - Release B
Both approaches have advantages and disadvantages.
IMO the answer to your question (changed a bit) Is XML the correct approach for saving structured data to a file? is - definitely yes! Nowadays XML is one of the standards for representing / manipulating / exchanging structured data and data generally (data kept in a string). As someone already mentioned INI files were not really meant to represent complex nested structures.
In contrast to PHP where you might be used to doing a lot of arrays and magic-string based stuff, C# is a Statically Typed language where it's usually recommended to create a proper, formally defined, structured Data Model which allows you to manipulate the Data you're dealing with in a strongly typed manner.
This means, for example, that if you're dealing with personal information related data, and you need to deal with the concepts of last name, first name, and age you will want to create a class containing these pieces of data in the form of Properties, like so:
public class Person
{
public string LastName {get;set;}
public string FirstName {get;set;}
public int Age {get;set;}
//And so on...
}
Notice how each property has an adequate Data Type that allows you to constrain what values it can contain. For example, the fact that the Age property is of type int (integer numbers) automatically means you can never have something like "abc" inside it, and code like this:
var person = new Person();
person.Age = "abc";
will also produce a compile-time error, rather than blowing up at run time, or producing any sorts of inconsistencies in stored data.
Likewise, if your Person objects (in the real world data you're trying to model) have a relation to, say an Address, you're also going to create the Address class:
public class Address
{
public string Line1 {get;set;}
public string Line2 {get;set;}
public string City {get;set;}
//And so on...
}
And then model this Person -> Address relationship by creating an additional property in the Person class:
public class Person
{
//.. All of the above.
public Address Address {get;set;}
}
Which can be illustrated with a diagram like this:
This approach has the following advantages:
It provides Compile Time checking for correctness of the code. Compile-Time errors can be trapped (and need to be corrected) very early in the development cycle. For example, you can't do something like:
person.LatsName where the property name LastName is mispelled LatsName because the compiler "knows" there is no such property in the object model and thus you recieve a compile-time error rather than having the application crash at run-time.
It provides IDE support for features such as AutoComplete because the IDE "knows" the object model you're dealing with and thus it knows what properties/methods/events (Members) every class has, and what are the expected parameters and data types for each of these.
So, to answer the overarching question, once you created a proper object model, you can use .Net's built-in Serialization/Deserialization mechanisms to transform instances of classes in your object model (with actual values and properties) to a data format that can be stored in a file on disk, such as XML.
Assuming you have a class for profile with all the relevant fields/properties, you can do
Profile profile = new Profile();
profile.actionA = "actionA"; // or whatever you have
var file = new System.IO.StreamWriter(#"c:\temp\Profile_as_xml.xml");
var writer = new System.Xml.Serialization.XmlSerializer(typeof(Profile));
writer.Serialize(file, profile);
file.Close();
See http://msdn.microsoft.com/en-us/library/ms172873.aspx
I am trying to serialize a list to json string using Json.NET but the return string has backslash within it, which in turn is failing a json parsing.
var x = from d in entities.Books.ToList()
select new
{
ID = d.ID,
BookName = d.BookName
};
return JsonConvert.SerializeObject(x.ToList());
The above code returns
"[{\"ID\":1,\"BookName\":\"MVC Music Store - Tutorial - v3.0\"},{\"ID\":2,\"BookName\":\"Pro.ASP.NET.MVC.3.Framework\"},{\"ID\":3,\"BookName\":\"Application Architecture Guide v2\"},{\"ID\":4,\"BookName\":\"Gang of Four Design Patterns\"},{\"ID\":5,\"BookName\":\"CS4 Pocket Reference\"}]"
which fails all JSON parsing. How can I remove these.
No. it doesn't
class Program
{
class Book
{
public int ID;
public string BookName;
}
static void Main()
{
var books = new List<Book> { new Book { ID = 1, BookName = "A" }, new Book { ID = 2, BookName = "B" } };
var x = from d in books
select new
{
ID = d.ID,
BookName = d.BookName
};
string str = JsonConvert.SerializeObject(x.ToList());
Console.WriteLine(str);
}
}
There could be two problems:
A) You are looking at the result from the debugger. To check for this, Put the JsonConvert in a temporary variable (like I did) and look at it with the debugger. Click on the arrow right of the hourglass and select Text Visualizer.
or
B) The calling method is transforming the object again to Json, so escaping everything.
string str = "Your string with slashes";
str = JToken.Parse({your string here}).ToString();
The JSON object is serialized twice.
I solved by:
Declaring the operation contract of the method response format to return JSON.
I changed the method to return an object instead of a string.
The serializing of Jason will be done automatically behind the scenes.
I was getting the same result, but with doubled escape shashes while I was unit testing some json serialization. Looking at my code I realized I am serializing the "expected" json string instead of the actual .net object. So, passing a json string to JsonConvert.SerializeObject(expectedJsonString) will simply escape it once over. This is how I came here, and this is the answer I wrote, when I realized I just did a coding mistake... Did you just realize yours?