Is it possible to make JavaScriptSerializer also populate properties without a setter? For example, a property like test.ID in the code below:
using System;
using System.Collections.Generic;
using System.Web.Script.Serialization;
namespace JavaScriptConverterTest
{
class Program
{
static void Main(string[] args)
{
List<test> list = new List<test>();
for (int i = 0; i < 2; i++)
{
list.Add(new test(Guid.NewGuid(), "Item #" + i));
}
JavaScriptSerializer serializer = new JavaScriptSerializer();
string jsonString = serializer.Serialize(list);
List<test> newList = serializer.Deserialize<List<test>>(jsonString);
Console.Read();
}
}
class test
{
private Guid id = Guid.Empty;
public Guid ID
{
get { return id; }
// Without a setter, JavaScriptSerializer doesn't populate this property.
// set { id = value; }
}
public string name = "";
public test()
{
}
public test(Guid id, string name)
{
this.id = id;
this.name = name;
}
}
}
You can use DataContractJsonSerializer which is built in .NET Framework and has its home at System.Runtime.Serialization.Json. You just need to decorate your field with DataMemberAttribute. Let's say you have this class:
class Foo
{
private string _boo;
public Foo(string boo) => _boo = boo;
public string Boo => _boo;
}
After decorating:
[DataContract]
class Foo
{
[DataMember] private string _boo;
public Foo(string boo) => _boo = boo;
public string Boo => _boo;
}
And testing:
private static void Main(string[] args)
{
var foo = new Foo("boo");
var serializer = new DataContractJsonSerializer(typeof(Foo));
string str;
using (var stream = new MemoryStream())
{
serializer.WriteObject(stream, foo);
str = Encoding.Default.GetString(stream.ToArray());
}
Console.WriteLine(str);
Foo loadedFoo;
using (var stream = new MemoryStream(Encoding.Default.GetBytes(str)))
{
loadedFoo = serializer.ReadObject(stream) as Foo;
}
Console.WriteLine(loadedFoo.Boo);
Console.ReadLine();
}
The loadedFoo that is constructed from the json string gets "boo" as value for _boo field.
Related
I have two problem. I need to serialize data to csv and xml but its turn out to be problematic for me.
As xml I desire to get something like:
<sentence>
<word>example1</word>
<word>example2</word>
<word>example3</word>
</sentence>
<sentence>
<word>example1</word>
<word>example2</word>
<word>example3</word>
</sentence>
My data its SentencedModel which contain inside collection of WordsModel. So it like: List<ICollection<string>>. Every position (sentence) in list have collection of string (words).
Class look like:
[Serializable]
public class WordsModel : IEnumerable<string>
{
[XmlRoot("Word")]
public ICollection<string> Words { get; set;}
public IEnumerator<string> GetEnumerator()
{
return this.Words.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.Words.GetEnumerator();
}
}
[Serializable]
public class SentencedModel : IEnumerable<WordsModel>
{
[XmlArray("Sentence"), XmlArrayItem(typeof(WordsModel), ElementName = "Words")]
public ICollection<WordsModel> Sentences { get; set; }
public SentencedModel()
{
this.Sentences = new List<WordsModel>();
}
public void Add(WordsModel words)
{
this.Sentences?.Add(words);
}
public IEnumerator<WordsModel> GetEnumerator()
{
return this.Sentences.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.Sentences.GetEnumerator();
}
}
My class which is Repositories for that:
public class WordsSeperapedBySentence
{
public SentencedModel WordsSeperatedBySentence { get; }
public WordsSeperapedBySentence()
{
this.WordsSeperatedBySentence = new SentencedModel();
}
public bool AddSentence(ICollection<string> words)
{
if (words == null) return false;
WordsModel wordsModel = new WordsModel();
wordsModel.Words = words;
this.WordsSeperatedBySentence.Add(wordsModel);
return true;
}
}
Here is my serializer class:
public class SerializeData
{
public string SerializeToXml(SentencedModel data)
{
XmlSerializer xmlSerializer = new XmlSerializer(typeof(SentencedModel));
using (StringWriter textWriter = new StringWriter())
{
xmlSerializer.Serialize(textWriter, data);
return textWriter.ToString();
}
}
public ToCsv(WordsSeperapedBySentence data)
{
//??
}
}
But after using
List<string> example1 = new List<string>();
example1.Add("Chris");
example1.Add("call");
example1.Add("Anna");
List<string> example2 = new List<string>();
example2.Add("Somebody");
example2.Add("call");
example2.Add("Wolf");
WordsModel words1 = new WordsModel();
WordsModel words2 = new WordsModel();
words1.Words = example1;
words2.Words = example2;
SentencedModel sentenced = new SentencedModel();
sentenced.Add(words1);
sentenced.Add(words2);
SerializeData serialize = new SerializeData();
var stringAsResult = serialize.SerializeToXml(sentenced);
Console.WriteLine(stringAsResult);
I got errors. Also I do not have idea how to storage them to CSV.
Could you help me?
Thank you in advance.
In order to save your data as CSV, you can use the following method which provides this output:
Chris,call,Anna
Somebody,call,Wolf
Each line is a sentence then all the words are separated by commas.
public string ToCsv(SentencedModel data)
{
var csvLines = data.Select(x => String.Join(",", x));
var csv = String.Join(Environment.NewLine, csvLines);
return csv;
}
I am still missing the XML part, if I do, I will edit the answer.
At least you have a part of it.
Edit Please find below the ToCsv with the fields being escaped based on the comments below.
public string ToCsv(SentencedModel data)
{
var csvLines = data.Sentences.Select(x => String.Join(",", x.Words.Select(w => EscapeForCsv(w))));
var csv = String.Join(Environment.NewLine, csvLines);
return csv;
}
private string EscapeForCsv(string input)
{
return String.Format("\"{0}\"", input.Replace("\"", "\"\"\""));
}
First: If you want to tokenize a text - I recommend:
use an array and not a list. For example: string[][]. The reason: List will locate 10%-20% more memory. You can convert a List to Array by .ToArray() (e.g. example1.ToArray) or use the C# 6.0 syntax:
string[][] sentence = new [] { {"Chris","called","Anna"}, {"Somebody","called","Wolf"} };
If possible: use the primitive datatypes - classes are to complex and slowdown your textprocessing.
Second: If you want to implement your own serializer try this approce:
public abstract class AbstractSerializer
{
public abstract void Serialize(string[][] model, string path);
}
public class XmlSerializer : AbstractSerializer
{
public override void Serialize(string[][] model, string path)
{
// your stuff
}
}
public class CsvSerializer : AbstractSerializer
{
public string LineSeparator { get; set; } = "\r\n";
public string ValueSeparator { get; set; } = ";";
public override void Serialize(string[][] model, string path)
{
var stb = new System.Text.StringBuilder();
for (int i = 0; i < model.Length; i++)
{
for (int j = 0; j < model[i].Length; j++)
{
// Example output:
// 0;0;Chris
// 0;1;call
// 0;2;Anna
// 1;0;Somebody
// 1;1;call
// 1;2;Wolf
stb.Append(string.Join(ValueSeparator, i, j, model[i][j], LineSeparator));
}
}
}
}
I'm relatively new to C# and I'm looking to replicate this following JSON expression:
{"itemData":[{"pile":"club","id":"100997087277"}]}
At present I have the following methods:
public class MoveItemValues
{
public string pile;
public Int64 id;
}
public class MoveItemRequestValues
{
public MoveItemValues itemData;
}
internal string moveItem(Int64 itemId, string pile)
{
string moveItemResponse;
MoveItemRequestValues bodyContent = new MoveItemRequestValues();
bodyContent.itemData = new MoveItemValues();
bodyContent.itemData.pile = pile;
bodyContent.itemData.id = itemId;
string jsonContent = JsonConvert.SerializeObject(bodyContent);
byte[] byteArray = Encoding.UTF8.GetBytes(jsonContent);
Console.WriteLine(jsonContent);
}
This produces:
"{"itemData":{"pile":"trade","id":100997087277}}"
But as you can see the square brackets are missing.
How would I go about finishing off achieving this?
itemData is an array in the json string.
FYI: You need to follow the C# naming guidelines. Property and method should be Pascal case.
public class MoveItemValues
{
public string Pile;
public Int64 Id;
}
public class MoveItemRequestValues
{
public IList<MoveItemValues> ItemData;
public MoveItemRequestValues()
{
ItemData = new List<MoveItemValues>();
}
}
static void MoveItem(Int64 itemId, string pile)
{
string moveItemResponse;
MoveItemRequestValues bodyContent = new MoveItemRequestValues();
bodyContent.ItemData = new List<MoveItemValues>()
{
new MoveItemValues {Pile = pile, Id = itemId}
};
var camelCaseFormatter = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
string jsonContent = JsonConvert.SerializeObject(bodyContent, camelCaseFormatter);
byte[] byteArray = Encoding.UTF8.GetBytes(jsonContent);
Console.WriteLine(jsonContent);
}
static void Main(string[] args)
{
MoveItem(100997087277, "trade");
Console.ReadLine();
}
Use List<>
public class MoveItemRequestValues
{
public List<MoveItemValues> itemData;
}
I have a little problem with .Net Json serializing
I have class withlist of strings an i need to serialize it as attribute for example:
original:
class:
kid{
int age;
String name;
List[String] toys;
}
result:
{
"age":10,
"name": Jane,
"toys":["one", "two", "three"]
}
i need
{
"age":10,
"name": Jane,
"toy_1": "one",
"toy_2": "two",
"toy_3": "three"
}
it's because of api. Is there any way how to do it?
Here's a dynamic solution that does not assume the number of toys:
public class kid
{
public int age;
public String name;
public List<String> toys;
public string ApiCustomView
{
get
{
Dictionary<string, string> result = new Dictionary<string, string>();
result.Add("age", age.ToString());
result.Add("name", name);
for (int ii = 0; ii < toys.Count; ii++)
{
result.Add(string.Format("toy_{0}", ii), toys[ii]);
}
return result.ToJSON();
}
}
}
usage:
static void Main(string[] args)
{
var k = new kid { age = 23, name = "Paolo", toys = new List<string>() };
k.toys.Add("Pippo");
k.toys.Add("Pluto");
Console.WriteLine(k.ApiCustomView);
Console.ReadLine();
}
It uses the extension you can find here: How to create JSON string in C#
namespace ExtensionMethods
{
public static class JSONHelper
{
public static string ToJSON(this object obj)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
return serializer.Serialize(obj);
}
public static string ToJSON(this object obj, int recursionDepth)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
serializer.RecursionLimit = recursionDepth;
return serializer.Serialize(obj);
}
}
}
As dcastro says, it's a weird API, and you should change it if you can to accept an array.
If you cannot you can try to create and anonymous type, so you will have something like that:
public object GetSerializationObjectForKid(Kid kid)
{
return new
{
age = kid.age,
name = kid.name,
toy_1 = toys.ElementAtOrDefault(0),
toy_2 = toys.ElementAtOrDefault(1),
toy_3 = toys.ElementAtOrDefault(2)
}
}
Than you can serialize this new anonymous object.
Here is an example of using an Anonymous Type to select members and give them names to match an api's requirements. It currently assumes that there will always be 3 "toys".
using System.Linq;
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Web.Script.Serialization;
namespace CommandLineProgram
{
public class DefaultProgram
{
public static void Main()
{
var kid1 = new kid()
{
age = 10,
name = "Jane",
toys = new List<String>
{
"one",
"two",
"three"
}
};
var asdf = new
{
age = kid1.age,
name = kid1.name,
toy_1 = kid1.toys[0],
toy_2 = kid1.toys[1],
toy_3 = kid1.toys[2]
};
JavaScriptSerializer ser = new JavaScriptSerializer();
String serialized = ser.Serialize(asdf);
Console.WriteLine(serialized);
}
}
public class kid
{
public int age;
public String name;
public List<String> toys;
}
}
Produces this output
{
"age" : 10,
"name" : "Jane",
"toy_1" : "one",
"toy_2" : "two",
"toy_3" : "three"
}
I ve found solution...it' s not clear, but it works
JObject data = JObject.Parse(JsonConvert.SerializeObject(exportAuc));
int i = 0;
foreach(String file in exportAuc.pdf_ostatni){
data.Add("pdf_ostatni_" + i.ToString(), file);
i++;
}
String output = data.ToString();
You can build a dynamic object adding the properties you need and then serialize it
dynamic jsonData = new System.Dynamic.ExpandoObject();
jsonData.age = kid.age;
jsonData.name = kid.name;
for (int i = 0; i < kid.toys.Count; i++)
{
((IDictionary<String, Object>)jsonData).Add(string.Format("toy_{0}", i), kid.toys[i]);
}
I am trying to create a jumplist for a LongListSelector, I used the AlphaKeyGroup example from MS as a basis.
Once I have created my list I then want to serialize it and store it until the app is next opened.
The problem I have is that the Key is null when I deserialize the ObservableCollection.
I have something like this on my Main Page
public ObservableCollection<AlphaKeyGroup<myClass>> myList { get; set; }
void process()
{
myList = AlphaKeyGroup<myClass>.CreateGroups(System.Threading.Thread.CurrentThread.CurrentUICulture);
getItemsAndAddtoList();
string serializedata = Serialize(myList);
}
void getItemsAndAddtoList()
{
List<myClass> templist=new List<myClass>();
templist.Add(new myClass("Alpha","A in the jumplist"));
templist.Add(new myClass("Beta", "B in the jumplist"));
templist.Add(new myClass("Cappa", "C in the Jumplist"));
addToList(templist.ToArray());
string data = Serialize(myList);
}
void addToList(myClass[] items)
{
if (this.mainList.Dispatcher.CheckAccess())
{
SortedLocaleGrouping slg = new SortedLocaleGrouping(System.Threading.Thread.CurrentThread.CurrentUICulture);
foreach (myClass item in items)
{
int index = 0;
if (slg.SupportsPhonetics)
{
}
else
{
index = slg.GetGroupIndex(item.description);
}
if (index >= 0 && index < myList.Count)
{
myList[index].Add(item);
}
}
}
else
{
this.mainList.Dispatcher.BeginInvoke(new Action<myClass[]>(addToList), new object[] { items });
}
}
public static string Serialize(object obj)
{
using (var sw = new StringWriter())
{
var serializer = new XmlSerializer(obj.GetType());
serializer.Serialize(sw, obj);
return sw.ToString();
}
}
If I break on return sw.ToString(); I can see something like this
<ArrayOfMyClass>
<myClass>
<description>Alpha</description>
<data>A in the jumplist</data>
</myClass>
</ArrayOfMyClass>
As you can see the key from the AlphaKeyGroup class is missing, if I then deserialise this back and set it as the LongListSelector ItemSource I get a Jumplist with No text values, just empty boxes.
public class myClass
{
public string description { get; set; }
public string data { get; set; }
public myClass()
{
}
public myClass(string Desc, string Data)
{
description = Desc;
data = Data;
}
}
public class AlphaKeyGroup<T> : ObservableCollection<T>
{
public delegate string GetKeyDelegate(T item);
public string Key { get; set; }
public AlphaKeyGroup(string key)
{
Key = key;
}
public AlphaKeyGroup()
{
}
public static ObservableCollection<AlphaKeyGroup<T>> CreateGroups(CultureInfo ci)
{
SortedLocaleGrouping slg = new SortedLocaleGrouping(ci);
ObservableCollection<AlphaKeyGroup<T>> list = new ObservableCollection<AlphaKeyGroup<T>>();
foreach (string key in slg.GroupDisplayNames)
{
list.Add(new AlphaKeyGroup<T>(key));
}
return list;
}
}
I am sure I am missing something simple, but I couldn't find a solution, I think it is to do with the Parameterless constructor, but I am not sure, I am quite new to C#.
This question already has answers here:
How to get the list of properties of a class?
(11 answers)
Closed 8 years ago.
I have a class
class ABC
{
Public int one = 10;
Public String two = "123";
public override string ToString()
{
}
}
My question i want to get fields information/values in String of Class "ABC" when ever i will create an object of that class. For example:
Public Class Test
{
public static void Main()
{
ABC a = new ABC();
a.ToString();
}
}
Now here I create an object a of class "ABC", then i want to override method of ToString() to get all fields values of class ABC in a string.
As solution this worked for me :
**Here is an other solution if we use static fields and fieldsInfo:**
class ReflectionTest
{
public static int Height = 2;
public static int Width = 10;
public static int Weight = 12;
public static string Name = "Got It";
public override string ToString()
{
string result = string.Empty;
Type type = typeof(ReflectionTest);
FieldInfo[] fields = type.GetFields();
foreach (var field in fields)
{
string name = field.Name;
object temp = field.GetValue(null);
result += "Name:" + name + ":" + temp.ToString() + System.Environment.NewLine;
}
return result;
}
}
public override string ToString()
{
Dictionary<string, string> fieldValues = new Dictionary<string, string>();
var fields = this.GetType().GetFields();
foreach (var field in fields)
{
fieldValues[field.Name] = field.GetValue(this).ToString();
}
return string.Join(", ", fieldValues.Select(x => string.Format("{0}: {1}", x.Key, x.Value)));
}
You could either use a property to retrieve the string, or override ToString(), both are shown:
public class ABC
{
private Int32 _one = 10;
public Int32 One { get { return _one; } }
private String _two = "123";
public String Two { get { return _two; } }
protected override ToString()
{
return _two;
}
}
not sure if this is what you mean;
public override ToString()
{
return string.Format("one: {1}{0}two: {2}", Environment.NewLine(), one, two);
}
So, here it is:
public class ABC
{
public int one;
public string two;
public int three;
public override string ToString()
{
string names = String.Empty;
System.Reflection.FieldInfo[] infos = this.GetType().GetFields();
foreach (System.Reflection.MemberInfo inf in infos)
{
if (names == String.Empty)
{
names = inf.Name;
}
else
{
names += ';' + inf.Name;
}
}
return names;
}
}
Enjoy!
This should do it:
public override string ToString() {
string s = "";
foreach(FieldInfo f in this.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public)) {
s += f.Name + "=" + f.GetValue(this).ToString() + "\r\n";
}
return s;
}
BindingFlags.Public reflects only public members. If you want private member too, use also the BindingFlags.Private flag.
You may use the this.GetType().GetFields() at object initialization, to call it only once.
This works for framework 2 also.
Change it to your needs.
Instead of using Reflection, you can use any of the following two approaches:
1: Here you can serialize your class object to a JSON object which would be more readable:
public override string ToString()
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(ABC));
string str;
using (MemoryStream stream = new MemoryStream())
{
serializer.WriteObject(stream, this);
stream.Position = 0;
using (StreamReader streamReader = new StreamReader(stream, Encoding.UTF8))
{
str = streamReader.ReadToEnd();
}
}
return str;
}
2: Here you can serialize your class object to XML which can be utilize some where else:
public override string ToString()
{
XmlSerializer s = new XmlSerializer(typeof(ABC));
StringBuilder sb = new StringBuilder();
var xtw = XmlTextWriter.Create(sb);
s.Serialize
(xtw, this);
return sb.ToString();
}
Finally Get solution to my problem :)
using System;
using System.Reflection;
using System.IO;
using System.Collections.Generic;
using System.Text;
class Program
{
static void Main(string[] args)
{
MyClass mC= new MyClass();
string result = mC.ToString();
}
}
class MyClass
{
string someValue = "One";
int someValue1 = -1;
bool someValue2 = false;
float someValue3 = 2.2f;
public string SomeValue
{
get{ return this.someValue;}
}
public int SomeValue1
{
get { return this.someValue1; }
}
public bool SomeValue2
{
get { return this.someValue2; }
}
public float SomeValue3
{
get { return this.someValue3; }
}
public override string ToString()
{
string result = string.Empty;
Type type = this.GetType();
PropertyInfo [] pInfo = type.GetProperties();
for (int i = 0; i <= pInfo.Length-1; i++)
{
Type internalType = this.GetType();
PropertyInfo pInfoObject = internalType.GetProperty(pInfo[i].Name);
object value = pInfoObject.GetValue(this,null);
result += pInfo[i].Name + " : " + value.ToString() + System.Environment.NewLine;
}
return result;
}
}
Here is an other solution if we use static fields and fieldsInfo:
class ReflectionTest
{
public static int Height = 2;
public static int Width = 10;
public static int Weight = 12;
public static string Name = "Got It";
public override string ToString()
{
string result = string.Empty;
Type type = typeof(ReflectionTest);
FieldInfo[] fields = type.GetFields();
foreach (var field in fields)
{
string name = field.Name;
object temp = field.GetValue(null);
result += "Name:" + name + ":" + temp.ToString() + System.Environment.NewLine;
}
return result;
}
}