How to save object as string in c# - c#

I have an object of student
Class Student
{
public Student()
{
name = "xyz";
roll = 20;
age = 16;
}
string name;
int roll;
int age;
}
Class Service
{
Student student = new Student();
string s = ???
// what I have to do for getting string like {"name" : "xyz", "roll" : 20, "age" :16}
}
I need the string from the above object.
If i serialize the object I am getting something with escape sequences.
Any help would be greatly appreciable.

Looks like what you really want is to serialize your object to JSON.
This can be easily done with JSON.NET library like this:
Student student = new Student();
var s = JsonConvert.Serialize(student);
If you need this in multiple places you can create an extension method or override the ToString method of Student class:
public class Student
{
public override string ToString()
{
return JsonConvert.Serialize(this);
}
}

You have to serialize your object. For example with the JavaScriptSerializer:
string s = new JavaScriptSerializer().Serialize(student);
Don't forget to add the following using
using System.Web.Script.Serialization;

This is a simplified example, use Vsevolod Goloviznin answer. It is better.
Just use toString();
string s = stuident.toString();
Add an overload to toString() in the class to get pretty print. My personal preferece is to output JSON.
Class Student
{
public Student()
{
name = "xyz";
roll = 20;
age = 16;
}
public override string toString(){
return "{name: " + name + ", roll: " + roll + ", age: " + age + "}";
}
string name;
int roll;
int age;
}

Override the ToString() method of your Student class
something like
public override string ToString()
{
return string.Format("Name: {0}, Roll: {1}, Age: {2}", name, roll, age);
}

The string in your example is JSON. You can use http://www.newtonsoft.com/jsont
to serialize:
string s = JsonConvert.SerializeObject(student);

You seem to want to serialize it to JSON, check out http://www.newtonsoft.com/json and use it to call string s = JsonConvert.SerializeObject(student);

Related

How to avoid calling Base class properties while creating derived class objects?

I have a base class ProductDetails which is responsible for parsing the productstring, there is another class SelfManufactured which inherits from the baseclass ProductDetails, there is another class - ThirdPartyProduct , which inherits from the SelfManufactured class and has additional details which are specific to this class, like ThirdPartyName, ThirdPartyAddress.
a) For SelfManufactured product the string should be - prefixed with 0
b) For ThirdPartyProduct product the string should be - prefixed with 1
workflow goes like this:
I create a ThirdPartyProduct object using following code:
private void ThirdParty_Click(object sender, RoutedEventArgs e)
{
ThirdPartyProduct thirdparty = new ThirdPartyProduct ("1000", "200", "PROD1",
"XYZW", "ABCD");
string thirdpartyProductString = thirdparty.ToString();
}
if you check the variable thirdpartyProductString in below code it is : appending 0 and then 1.
It appends 0 and then 1 instead what I would like to have is only "1" getting prefixed.
I guess since SelfManufactured class is also called while creating ThirdParty object, it keeps appending values, I would like to have a way that ToString() does not append values when not needed.
ProductDetails.cs
using System;
namespace product
{
public class ProductDetails
{
private readonly string _productString;
public string ProductString
{
get => ToString();
}
public ProductDetails(string productId, string productName, string productLot)
{
_productString = // somevalue here....
}
public override string MyString()
{
return _productString;
}
}
}
SelfManufactured.cs
public class SelfManufactured : ProductDetails
{
public override string MyString()
{
string str = string.Empty;
str = "additional value of 0" + // append the identifier as '0' with product string
return str;
}
}
ThirdPartyProduct.cs
public class ThirdPartyProduct : SelfManufactured
{
public string ThirdPartyName { get; set; }
public string ThirdPartyAddress { get; set; }
public override string MyString()
{
string str = string.Empty;
// append the identifier as '1' with product string and add additional details with the string.
return str;
}
}
Since you are calling base.ToString() in "ThirdPartyProduct" class, it obviously calls the base class ToString() method and it adds "0" to it and making the final string as "101000200PROD1XYZWABCD"
If you don't want to do that then you can refer "ProductString" property of ProductDetails class directly from ToString() method of ThirdPartyProduct class. See below my changes
ProductDetails.cs - I am returning the private read-only from here.
public string ProductString
{
get { return _productString; }
}
Then the ToString() method of ThirdPartyProduct.cs class made to following changes
public override string ToString()
{
string str = string.Empty;
// append the identifier as '0' with product string and add additional details with the string.
str = (int)ProductType.ThirdParty + ProductString + ThirdPartyName + ThirdPartyAddress;
return str;
}
Made changes at the following line -
str = (int)ProductType.ThirdParty + base.ToString() + ThirdPartyName + ThirdPartyAddress;
to
str = (int)ProductType.ThirdParty + ProductString + ThirdPartyName + ThirdPartyAddress;
Note:- I hope always the ThirdPartyProduct class should not append "0", then above solution should be fine, else you need to think of other approach for the calculations.
You already have a property in class ProductDetails called "TypeOfProduct". So in SelfManufactured.ToString(), instead of hard-coding the product type, use the property's value:
str = (int)TypeOfProduct + base.ToString();
Then, in ThirdPartyProduct, there's no need to use the product type as this is taken care of in the base class. So instead call base.ToString() followed by the class-specific details:
str = base.ToString() + ThirdPartyName + ThirdPartyAddress;

Convert a string to JSON object

I have a JsonString:
"baseAbilities":"[{"baseId":1,"name":"Focused Elemental Strike"}]"
I want to make it:
"baseAbilities":[{"baseId":1,"name":"Focused Elemental Strike"}]
So the it is easy for JSON utility to deserialise it. Any suggestions
EDIT:
This is basically a json object in the following Json String:
{"data”: [{"id":9,"name":"Sam5","baseAbilities":"[{\"baseId\":1,\"name\":\"Focused Elemental Strike\"},{\"baseId\":9,\"name\":\"Cleanse\"}]"]}
The backend developer saved JSON in a column baseAbilities as a string. Now I don't have the access to Back end APIs. So i need to convert this string baseAbilities to JSON so that I can access objects inside it.
Now I use these classes to decode JSON:
[System.Serializable]
class GetBAResult
{
public List<bounceAbilityData> data;
}
[System.Serializable]
class bounceAbilityData
{
public int id;
public string name;
public string baseAbilities;
}
And this is how I decode JSON:
GetBAResult P = JsonUtility.FromJson<GetBAResult>(w.text);
for (int i = 0; i < P.data.Count; i++)
{
Debug.Log(P.data[i].name);
GameObject layoutGroupNameButton = (GameObject)Instantiate(prefabBAButton);
layoutGroupNameButton.transform.SetParent(ParentPanel, false);
layoutGroupNameButton.GetComponentInChildren<Text>().text = P.data[i].name;
layoutGroupNameButton.GetComponent<BounceAbilityButton>().id = P.data[i].id;
layoutGroupNameButton.GetComponent<BounceAbilityButton>().name = P.data[i].name;
Debug.Log(P.data[i].baseAbilities);
}
I need to get things inside baseAbilities such as "baseID" and "name"
Have you tried this?
JObject json = JObject.Parse(str);
documentation
With a class set of
[System.Serializable]
class GetBAResult
{
public List<bounceAbilityData> data;
}
[System.Serializable]
class bounceAbilityData
{
public int id;
public string name;
public List<BaseAbilities> baseAbilities;
}
[System.Serializable]
class BaseAbilities
{
public int baseId;
public string name;
}
You can then use the following to Deserialize your JSON to an instance of GetBAResult
string json = "{\"data\":[{\"id\":9,\"name\":\"Sam5\",\"baseAbilities\":[{\"baseId\":1,\"name\":\"Focused Elemental Strike\"},{\"baseId\":9,\"name\":\"Cleanse\"}]}]}";
GetBAResult myObject = JsonUtility.FromJson<GetBAResult>(json);
BaseAbilities abilities = myObject.data[0].baseAbilities[0];
You can read more about JSON Deserialization here on the Unity Documentation
https://docs.unity3d.com/Manual/JSONSerialization.html
The original questions says that you want to change:
"baseAbilities":"[{"baseId":1,"name":"Focused Elemental Strike"}]"
to
"baseAbilities":[{"baseId":1,"name":"Focused Elemental Strike"}]
Basically, you want to remove the " before the [{" then remove the final " at the end of the json string. The problem is that even after you do this, "baseAbilities":[{"baseId":1,"name":"Focused Elemental Strike"}] cannot be serialized to json.
You need to add { in front of it and } at the end of it.
The final string after adding { in front of it and } at the end is:
{"baseAbilities":[{"baseId":1,"name":"Focused Elemental Strike"}]}
The fixJson function below fixes those problems and this is how to use it:
[System.Serializable]
public class BaseAbility
{
public int id;
public string name;
}
[System.Serializable]
public class GetBAResult
{
public List<BaseAbility> baseAbilities;
}
void Start()
{
// StartCoroutine(RespawnPlayer());
string fixedJson = fixJson(w.text);
//string fixedJson = fixJson("\"baseAbilities\":\"[{\"id\":1,\"name\":\"Focused Elemental Strike\"}]\"");
Debug.Log("Fixed Json: " + fixedJson);
GetBAResult P = JsonUtility.FromJson<GetBAResult>(fixedJson);
Debug.Log("Count Json: " + P.baseAbilities.Count);
for (int i = 0; i < P.baseAbilities.Count; i++)
{
Debug.Log("Name: " + P.baseAbilities[i].name);
Debug.Log("Base ID: " + P.baseAbilities[i].id);
}
}
string fixJson(string jsonToFix)
{
//First srting with `"` that will be removed
const string firstString = "\"baseAbilities\":\"";
//Last string with `"` that will be removed
const string lastString = "\"";
//String that will be used to fix the "baseAbilities":"[ with the `"`
const string fixedFirstString = "\"baseAbilities\":";
//Get the first Index of firstString
int firstIndex = jsonToFix.IndexOf(firstString);
//Remove First Index of `firstString`
jsonToFix = jsonToFix.Remove(firstIndex, firstString.Length);
int lastIndex = jsonToFix.LastIndexOf(lastString);
//Remove everything from Last `lastString` to the end
jsonToFix = jsonToFix.Remove(lastIndex);
//Append the correct/fixed string without `"` to the beginning of the json data
jsonToFix = fixedFirstString + jsonToFix;
//Add `{` to the begging and `}` to the end of the json data
jsonToFix = "{" + jsonToFix + "}";
return jsonToFix;
}
Let's say you have a class like this:
using System;
using System.Collections.Generic;
using UnityEngine;
public class JsonTest : MonoBehaviour
{
[Serializable]
public class Ability
{
public int baseId;
public string name;
public Ability(int _baseId, string _name)
{
baseId = _baseId;
name = _name;
}
}
public class Abilities
{
public List<Ability> baseAbilities;
public Abilities(List<Ability> _baseAbilities)
{
baseAbilities = _baseAbilities;
}
}
void Start()
{
List<Ability> list = new List<Ability>();
list.Add(new Ability(1, "Focused Elemental Strike"));
list.Add(new Ability(2, "Another ability"));
Abilities baseAbilities = new Abilities(list);
string serializedAbilites = JsonUtility.ToJson(baseAbilities);
Debug.Log(serializedAbilites);
Abilities deserializedAbilites = JsonUtility.FromJson<Abilities>(serializedAbilites);
}
}
You have an Ability class marked as Serializable containing and id and a name.
You have another class Abilities used as a wrapper for a list of abilities.
You can then serialize a list of abilities using JsonUtility.ToJson(). Which will give you the following string:
{
"baseAbilities": [
{
"baseId": 1,
"name": "Focused Elemental Strike"
},
{
"baseId": 2,
"name": "Another ability"
}
]
}
And of course you can deserialize it using JsonUtility.FromJson().
Is this what your looking for ?

Array.find() provides strange results

I am in middle of writing an assignment for my part time programming course. The issues with my code is the array.find() and results of that search. It should(In my theory) search the array for information and then post them to the user, however what comes out from all of the searches is the same thing: ass2task1.Program+customer Here are only parts of the code becouse out teacher told us we can post question on the internet as long as we don't post our entire codes
struct customer
{
public int customernumber;
public string customersurname;
public string customerforname;
public string customerstreet;
public string customertown;
public DateTime customerdob;
}
static void Main(string[] args)
{
customer[] customerdetails = new customer[99];
int selector = 0;
int selector2 = 0;
string vtemp = "";
string ctemp = "";
int searchnumber;
string searchforename; //variable/ array declaring
string searchsurname;
string searchtown;
DateTime searchdob;
customer resultnumber;
customer resultforename;
customer resultsurname;
customer resulttown;
customer resultdob;
if (selector2 == 2)
{
Console.Clear();
Console.WriteLine("Enter the forename you are looking for: ");
searchforename = (Console.ReadLine());
resultforename = Array.Find(customerdetails, customer => customer.customerforname == searchforename);
Console.Clear();
Console.WriteLine("Enter the surname you are looking for: "); // all of the searches comes out with ass2task1.Program+customer result
searchsurname = (Console.ReadLine());
resultsurname = Array.Find(customerdetails, customer => customer.customersurname == searchsurname);
Console.WriteLine("The forename resuts:" + resultforename);
Console.WriteLine("The surname resuts:" + resultsurname);
Array.Find() will return the object that matches a predicate, if you want the property value, you would need to do something like: resultforename.customerforname or something similar.
If it is not found, then a default value will be returned, so check for nulls etc.
When you convert an object to a string ("The forename resuts:" + resultforename) it calls the objects ToString() method. Define an appropriate ToString() method:
struct customer
{
public int customernumber;
public string customersurname;
public string customerforname;
public string customerstreet;
public string customertown;
public DateTime customerdob;
public override string ToString()
{
return customersurname + ", " + customerforname;
}
}
To (attempt to) expand on Ric and clcto's answers. The reason you're getting the struct name in your
Console.WriteLine("The forename resuts:" + resultforename);
Console.WriteLine("The surname resuts:" + resultsurname);
Your resultforename is of struct customer - by default Console.WriteLine(struct) does not know how to represent a complex object as a string.
As suggested you could do
Console.WriteLine("The forename resuts:" + resultforename.customerforname);
Or provide your own .ToString() method for the struct as clcto pointed out - doing this you're basically telling Console.WriteLine (or any string representation) how to represent a struct of customer as string.
Don't know if this will help, or make it even less clear. But given:
public struct Foo
{
public string Bar { get; set; }
}
public struct FooTwo
{
public string Bar { get; set; }
public override string ToString()
{
return "This is how to represent a Foo2 as string: " + Bar;
}
}
Foo[] foos = new Foo[99];
Foo foundFoo = foos[0]; // This is equivalent to your find statement... setting a foundFoo local variable to a Foo struct
string foundBar = foos[0].Bar; // This is another way to get to what you're trying to accoomplish, setting a string value representation of your found object.
Console.WriteLine(foundFoo); // Doesn't know how to deal with printing out a Foo struct - simply writes [namespace].Foo
Console.WriteLine(foundFoo.Bar); // Outputs Foo.Bar value
Console.WriteLine(foundBar); // Outputs Foo.Bar value
FooTwo foo2 = new FooTwo();
foo2.Bar = "test bar";
Console.WriteLine(foo2); // outputs: "This is how to represent a Foo2 as string: test bar"

Read values from a non-delimited string into class object

I have a string with the following structure:
Student Name________AgeAddress_______________________Bithday___Lvl
Example:
Jonh Smith 016Some place in NY, USA 01/01/2014L01
As you can see, there is no delimited character like | or ,
Also, there is no space between fields (if you check, there is no space between Age/Address and Birthday/Level.
The size of each field is static so if data's length is less then it will contains white spaces.
I have a class that need to be filled with that information:
public class StudentData
{
public char[] _name = new char[20];
public string name;
public char[] _age = new char[3];
public string age;
public char[] _address = new char[30];
public string address;
public char[] _bday = new char[10];
public string bday;
public char[] _level = new char[3];
public string level;
}
Is there any way to do this automatically and dynamically?
I mean I really don't want to code like this:
myClass.name = stringLine.substring(0,19);
myClass.age = stringLine.substring(20,22);
That's because I have way more fields that the ones added in this example & way more string lines with other different data.
Update: There were supposed to be a lot of spaces between "Smith" and "016", but I don't know how to edit it.
Update2: If I use StringReader.Read() I can evade to use substring and indexes, but it isn't still so dynamically because I would need to repeat those 3 lines for each field.
StringReader reader = new StringReader(stringLine);
reader.Read(myClass._name, 0 myClass._name.Length);
myClass.name = new string(myClass._name);
Given your requirement I came up with an interesting solution. All be-it it may be more complex and longer than using the String.SubString() method as stated.
However this solution is transferable to other types and other string. I used a concept of Attributes, Properties, and Reflection to parse a string by a Fixed Length and setting the class Properties.
Note I did change your StudentData class to follow a more conventional coding style. Following this handy guide on MSDN: http://msdn.microsoft.com/en-us/library/xzf533w0(v=vs.71).aspx
Here is the new StudentData class. Note it uses the properties as opposed to fields. (Not discussed here).
public class StudentData
{
string name;
string age;
string address;
string bday;
string level;
[FixedLengthDelimeter(0, 20)]
public string Name { get { return this.name; } set { this.name = value; } }
[FixedLengthDelimeter(1, 3)]
public string Age { get { return this.age; } set { this.age = value; } }
[FixedLengthDelimeter(2, 30)]
public string Address { get { return this.address; } set { this.address = value; } }
[FixedLengthDelimeter(3, 10)]
public string BDay { get { return this.bday; } set { this.bday = value; } }
[FixedLengthDelimeter(4, 3)]
public string Level { get { return this.level; } set { this.level = value; } }
}
Note on each of the properties there is an Attribute called FixedLengthDelimeter that takes two parameters.
OrderNumber
FixedLength
The OrderNumber parameter denotes the order in the string (not the position) but the order in which we process from the string. The second parameter denotes the Length of the string when parsing the string. Here is the full attribute class.
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public sealed class FixedLengthDelimeterAttribute : Attribute
{
public FixedLengthDelimeterAttribute(int orderNumber, int fixedLength)
{
this.fixedLength = fixedLength;
this.orderNumber = orderNumber;
}
readonly int fixedLength;
readonly int orderNumber;
public int FixedLength { get { return this.fixedLength; } }
public int OrderNumber { get { return this.orderNumber; } }
}
Now the attribute is simple enough. Accepts the two paramters we discussed eariler in the constructor.
Finally there is another method to parse the string into the object type such as.
public static class FixedLengthFormatter
{
public static T ParseString<T>(string inputString)
{
Type tType = typeof(T);
var properties = tType.GetProperties(BindingFlags.Instance | BindingFlags.Public); //;.Where(x => x.GetCustomAttributes(typeof(FixedLengthDelimeterAttribute), false).Count() > 0);
T newT = (T)Activator.CreateInstance(tType);
Dictionary<PropertyInfo, FixedLengthDelimeterAttribute> dictionary = new Dictionary<PropertyInfo, FixedLengthDelimeterAttribute>();
foreach (var property in properties)
{
var atts = property.GetCustomAttributes(typeof(FixedLengthDelimeterAttribute), false);
if (atts.Length == 0)
continue;
dictionary[property] = atts[0] as FixedLengthDelimeterAttribute;
}
foreach (var kvp in dictionary.OrderBy(x => x.Value.OrderNumber))
{
int length = kvp.Value.FixedLength;
if (inputString.Length < length)
throw new Exception("error on attribute order number:" + kvp.Value.OrderNumber + " the string is too short.");
string piece = inputString.Substring(0, length);
inputString = inputString.Substring(length);
kvp.Key.SetValue(newT, piece.Trim(), null);
}
return newT;
}
}
The method above is what does the string parsing. It is a pretty basic utility that reads all the properties that have the FixedLengthDelimeter attribute applied a Dictionary. That dictionary is then enumerated (ordered by OrderNumber) and then calling the SubString() method twice on the input string.
The first substring is to parse the next Token while the second substring resets the inputString to start processing the next token.
Finally as it is parsing the string it is then applying the parsed string to the property of the class Type provided to the method.
Now this can be used simply like this:
string data1 = "Jonh Smith 016Some place in NY, USA 01/01/2014L01";
StudentData student = FixedLengthFormatter.ParseString<StudentData>(data1);
What this does:
Parses a string against property attributes in a fixed length format.
What this does not do:
It does convert the parsed strings to another type. Therefore all the properties must be a string. (this can be easily adapted by adding some type casting logic in).
It is not well tested. This is only tested against a few samples.
It is not by all means the only or best solution out there.
You could use FileHelpers library (NuGet).
Just define the structure of your input file with attributes:
[FixedLengthRecord]
public class StudentData
{
[FieldFixedLength(20)]
[FieldTrim(TrimMode.Right)]
public string name;
[FieldFixedLength(3)]
public string age;
[FieldFixedLength(30)]
[FieldTrim(TrimMode.Right)]
public string address;
[FieldFixedLength(10)]
public string bday;
[FieldFixedLength(3)]
public string level;
}
Then simply read the file using FileHelperEngine<T>:
var engine = new FileHelperEngine<StudentData>();
var students = engine.ReadFile(filename);

Classes convertor

I have the following class People:
class People
{
public enum Gender
{
Man = 'w',
Woman = 'f'
}
public struct Person
{
public string First, Last;
public Gender Gender;
public int Age;
public float Height, Weight;
}
public struct Group
{
public int Members;
public string Name;
}
}
Now, we are located in the class Program:
class Program
{
static void Main( string[] args )
{
People.Person p = new People.Person();
p.First = "Victor";
p.Last = "Barbu";
p.Age = 14;
p.Height = 175;
p.Weight = 62;
p.Gender = People.Gender.Man;
Console.ReadLine();
}
}
I want to put a line like this:
Console.Write( x.toString() );
How can I customize the x.toString() method, so the result to be the following in the Console
Victor Barbu
14 years
Man
175 cm
62 kg
?
Thanks in advance!
Just overrive the ToString() method
public override string ToString()
{
// return the value you want here.
}
You want to override the ToString method in the Person class. See: http://msdn.microsoft.com/en-us/library/ms173154(v=vs.80).aspx
In your case
public class Person
{
// Snip
public override string ToString()
{
return this.First + " " + this.Last;
}
}
If you then do
Console.WriteLine(person.ToString());
The expected output would be the first and last name, you can obviously extend this to include your other fields and line breaks, etc.
Side note; what you are doing is really "pretty printing" I would suggest creating a static method "public static string PrettyPrintPerson(Person p)" or similar, to deal with textual formatting of the class.
class People
{
public override string ToString()
{
//This will return exactly what you just put down with line breaks
// then just call person.ToString()
return string.format("{1} {2}{0}{3} years{0}{4}{0}{5} cm{0}{6} kg", Environment.NewLine,
First, Last, Age, Gender, Height, Weight);
}
}

Categories

Resources