I have written a C# class (KvpHash) for consumption in VBA which provides additional useful functionality around a Hashtable. In my VBA code I have an extensive Rubberduck test suite for the KvpHash class that shows all functions of the class work as expected except for the fact that I cannot change the value of an item.
From VBA I get the error message
424 'Object required'
In the C# class the interface code is
dynamic this[dynamic Key] { get; set; }
and the implementation is
public dynamic this[dynamic Key]
{
get
{
return MyKvpHash[Key];
}
set
{
MyKvpHash[Key] = value;
}
}
where MyKvpHash is defined as
private Hashtable MyKvpHash = new Hashtable();
If I add the mscorelib reference to VBA I can create a Hashtable directly in VBA where it is fully possible to change the value of an item in the Hash Table.
I'd appreciate pointers as to what I am doing wrong in the C# code which causes the object required error.
Edited: to add example VBA code
Using a native HashTable
Public Sub TestHashtable()
' requires reference to mscorlib.dll
Dim myHt As Hashtable
Set myHt = New Hashtable
myHt.Add 5, "Hello5"
myHt.Add 10, "Hello10"
Debug.Print myHt.Item(10)
Debug.Print myHt.Item(5)
' the next line works as expected
myHt.Item(10) = "A new world"
Debug.Print myHt.Item(10)
End Sub
Gives the output
Hello10
Hello5
A new world
Using my KvpHash class ( a wrapper for HashTable)
Public Sub TestKvpHash()
Dim myHt As VBAExtensions.KvpHash
' KvpHash is a C# wrapper for a System.Collections.HashTable
Set myHt = New KvpHash
myHt.AddByKey 5, "Hello5"
myHt.AddByKey 10, "Hello10"
Debug.Print myHt.Item(10)
Debug.Print myHt.Item(5)
' The next line produces error 424
myHt.Item(10) = "A new world"
Debug.Print myHt.Item(10)
End Sub
Gives the output
Hello10
Hello5
and then stops with the 424 error.
Edited to add the full C# code as requested.
Seems there is no file hosting and I don't have another means of providing a link so I'v inserted the relevant code below. The code was originally based on a Dictionary but I updated it to Hashtable when I first found I couldn't assign to an item. That switch didn't change the behaviour of my code. Please be aware that I'm not a professional programmer and that the supplied code is essentially my first foray into C#. Typically I write Word VBA macros for my own consumption.
// VBAExtensions
//
// C# Library module for VBA
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Linq;
namespace VBAExtensions
{
/// <summary>
/// Enum for accessing the kvphash structure returned by Method Cohorts
/// </summary>
public enum CohortType
{
/// <summary>1 = the keys in A plus keys in B that are not shared</summary>
KeysInAAndOnlyB = 1,
/// <summary>2 = the Keys from B in A where B has a different value to A</summary>
KeysInAandBWithDifferentValues,
/// <summary>3 = the keys that are only in A and only in B</summary>
KeysNotInAandB,
/// <summary>4 = the keys that are inA and B </summary>
KeysInAandB,
/// <summary>5 = the keys in A only </summary>
KeysInAOnly,
/// <summary>6 = the keys in B only</summary>
KeysInBOnly
}
/// <summary>
/// KvpHash is a C# class for VBA which implements a Key/Value HashTable
/// The object is a morer flexible version of the Scripting.Dictionary
/// </summary>
[Guid("30F9294B-11B4-4D91-9D7C-7FF02ADB3F11")]
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IKvpHash
{
/// <summary>
/// Returns/Sets the "Value" specified by "Key" (i) of a Key/Value Pair
/// </summary>
/// <param name="Key"></param>
/// <returns>Type used in Set statement (C# dynamic)</returns>
dynamic this[dynamic Key] { get; set; }
/// <summary>
/// Adds "Value" to the KvpHash using an integer (VBA Long) Key.
/// The integer key is based on the first available integer greater than or
/// equal to the Count of the KvpHash
/// </summary>
/// <param name="Value"></param>
void AddByIndex(dynamic Value);
/// <summary>
/// Populates this KvpHash using AddByIndex for each character in the string
/// </summary>
/// <param name="this_string"></param>
void AddByIndexAsChars(string this_string);
/// <summary>
/// Pupulates this KvpHash using AddByIndex for each substring in this_string delineated by this_seperator
/// </summary>
/// <param name="this_string"></param>
/// <param name="this_seperator"></param>
void AddByIndexAsSubStr(string this_string, string this_seperator = ",");
/// <summary>
/// Pupulates a KvpHash using AddByIndex for each array item
/// </summary>
/// <param name="this_array"></param>
void AddByIndexFromArray(dynamic this_array);
/// <summary>
/// Adds "Value" to the KvpHash with a key pf "Key"
/// </summary>
/// <param name="Key"></param>
/// <param name="Value"></param>
void AddByKey(dynamic Key, dynamic Value);
/// <summary>
/// Groups the keys of the two KvpHash
/// </summary>
/// <param name="ArgKvpHash"></param>
/// <returns>An array of 6 KvpHash
/// keys in a {1,2,3,4,5,6}
/// keys in b {1,2,3,6,7,8}
/// 1 = the keys in A plus keys in B that are not shared {1,2,3( from A),4,5,6,7,8}
/// 2 = the Keys from B in A where B has a different value to A {3( from B) if value is different}
/// 3 = the keys that are only in A and only in B {4,5,7,8}
/// 4 = the keys that are in A and B {1,2,3,6}
/// 5 = the keys in A only {4,5}
/// 6 = the keys in B only {7,8}
/// </returns>
KvpHash Cohorts(KvpHash ArgKvpHash);
/// <summary>
/// The number of key/vaue pairs in the KvpHash
/// </summary>
/// <returns>Long</returns>
int Count();
///// <summary>
///// Return the IEnumerator interface for KvpHash
///// </summary>
///// <returns>IEnumerator</returns>
//IEnumerator GetEnumerator();
/// <summary>
/// Gets the "Key" for the first ocurrence of "Value" in the KvpHash.
/// </summary>
/// <param name="Value"></param>
/// <returns>Key</returns>
dynamic GetKey(dynamic Value);
/// <summary>
/// Returns a variant array of the Keys of the KvpHash
/// </summary>
/// /// <returns>Variant Array</returns>
dynamic[] GetKeys();
/// <summary>
/// Returns a variant array of the values of the KvpHash
/// </summary>
/// <returns>Variant Array</returns>
dynamic[] GetValues();
/// <summary>
/// True if the "Key" exists in the keys of the KvpHash
/// </summary>
/// <param name="Key"></param>
/// <returns>Boolean</returns>
bool HoldsKey(dynamic Key);
/// <summary>
/// True if the "Value" exists in the values of the KvpHash
/// </summary>
/// <param name="Value"></param>
/// <returns>Boolean</returns>
bool HoldsValue(dynamic Value);
/// <summary>
/// True if the KvpHash holds 0 key/value pairs
/// </summary>
/// <returns>Boolean</returns>
bool IsEmpty();
/// <summary>
/// True if the KvpHash holds one or more key/value pairs
/// </summary>
/// <returns>Boolean</returns>
bool IsNotEmpty();
/// <summary>
/// True is the "Key" is not found in the keys of the KvpHash
/// </summary>
/// <param name="Key"></param>
/// <returns>Boolean</returns>
bool LacksKey(dynamic Key);
/// <summary>
/// True if the "Value" is not found in the values of the KvpHash
/// </summary>
/// <param name="Value"></param>
/// <returns>Boolean</returns>
bool LacksValue(dynamic Value);
/// <summary>
/// Reverses the Key/Value pairs in a KvpHash
/// </summary>
/// <returns>New KvpHash where:
/// KvpHash.Value(1) = KvpHash Unique values as Value/Key pairs
/// KvpHash.Value(2) = KvpHash Non unique values as Key/Value pairs</returns>
KvpHash Mirror();
/// <summary>
/// Removes the Key/Value pair spacified by "Key" from the KvpHash
/// </summary>
/// <param name="Key"></param>
void Remove(dynamic Key);
/// <summary>
/// Removes all Key/Value pairs from the KvpHash
/// </summary>
void RemoveAll();
/// <summary>
/// Returns true if the Values in KvpHash are unique.
/// </summary>
/// <returns>Boolean</returns>
bool ValuesAreUnique();
/// <summary>
/// Returns true if the Values in KvpHash are not unique.
/// </summary>
/// <returns>Boolean</returns>
bool ValuesAreNotUnique();
}
[Guid("87E5A539-FDB3-40D0-9CCD-C817F9893C08")]
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class KvpHash : IKvpHash, IEnumerable
{
private Hashtable MyKvpHash = new Hashtable();
public dynamic this[dynamic Key]
{
get
{
return MyKvpHash[Key];
}
set
{
MyKvpHash[Key] = value;
}
}
public void AddByIndex(dynamic Value)
{
int my_index = MyKvpHash.Count + 1;
while (MyKvpHash.ContainsKey(my_index))
{
my_index++;
}
MyKvpHash.Add(my_index, Value);
}
public void AddByIndexAsChars(string this_string)
{
int my_index = MyKvpHash.Count + 1;
while (MyKvpHash.ContainsKey(my_index))
{
my_index++;
}
char[] MyArray = this_string.ToCharArray();
MyKvpHash.Clear();
for (int i = 0; i <= MyArray.GetUpperBound(0); i++)
{
//KvpHash uses ordinal indexes
MyKvpHash.Add(i + 1, MyArray[i].ToString());
}
}
public void AddByIndexAsSubStr(string this_string, string this_seperator = ",")
{
int my_index = MyKvpHash.Count + 1;
while (MyKvpHash.ContainsKey(my_index))
{
my_index++;
}
string[] MyArray = this_string.Split(this_seperator.ToArray());
for (int i = 0; i <= MyArray.GetUpperBound(0); i++)
{
//KvpHash uses ordinal indexes
MyKvpHash.Add(i + 1, MyArray[i]);
}
}
public void AddByIndexFromArray(dynamic this_array)
{
int my_index = MyKvpHash.Count + 1;
while (MyKvpHash.ContainsKey(my_index))
{
my_index++;
}
for (int i = 0; i <= this_array.GetUpperBound(0); i++)
{
//KvpHash uses ordinal indexes
MyKvpHash.Add(i + 1, this_array[i]);
}
}
public void AddByKey(dynamic Key, dynamic Value)
{
MyKvpHash.Add(Key, Value);
}
public KvpHash Cohorts(KvpHash ArgKvpHash)
{
KvpHash ResultKvpHash = new KvpHash();
// VBA reports object not set error if the resuly KvpHash are not newed
for (int i = 1; i < 7; i++)
{
ResultKvpHash.AddByKey(i, new KvpHash());
}
foreach (DictionaryEntry MyKvpHashPair in MyKvpHash)
{
// A plus unique in B
ResultKvpHash[1].AddByKey(MyKvpHashPair.Key, MyKvpHashPair.Value);
if (ArgKvpHash.LacksKey(MyKvpHashPair.Key)) // problem is here
{
// In A only or in B only
ResultKvpHash[3].AddByKey(MyKvpHashPair.Key, MyKvpHashPair.Value);
// In A only
ResultKvpHash[5].AddByKey(MyKvpHashPair.Key, MyKvpHashPair.Value);
}
else
{
// In A and In B
ResultKvpHash[4].AddByKey(MyKvpHashPair.Key, MyKvpHashPair.Value);
}
}
foreach (dynamic MyKey in ArgKvpHash.GetKeys())
{
// B in A with different value
if (ResultKvpHash[1].LacksKey(MyKey)) // Result 0 will contain all of A
{
ResultKvpHash[1].AddByKey(MyKey, ArgKvpHash[MyKey]);
ResultKvpHash[3].AddByKey(MyKey, ArgKvpHash[MyKey]);
ResultKvpHash[6].AddByKey(MyKey, ArgKvpHash[MyKey]);
}
else
{
if (ResultKvpHash[1][MyKey] != ArgKvpHash[MyKey])
{
ResultKvpHash[2].AddByKey(MyKey, ArgKvpHash[MyKey]);
}
}
}
return ResultKvpHash;
}
public Int32 Count()
{
return MyKvpHash.Count;
}
public bool IsEmpty()
{
return MyKvpHash.Count == 0;
}
public bool IsNotEmpty()
{
return !IsEmpty();
}
public IEnumerator GetEnumerator()
{
foreach (DictionaryEntry my_pair in MyKvpHash)
{
yield return my_pair.Value;
}
}
public dynamic GetKey(dynamic Value)
{
return this.Mirror()[1][Value];
}
public dynamic[] GetKeys()
{
return (dynamic[]) MyKvpHash.Keys;
}
public dynamic[] GetValues()
{
return (dynamic[]) MyKvpHash.Values;
}
public bool HoldsKey(dynamic Key)
{
return MyKvpHash.ContainsKey(Key);
}
public bool HoldsValue(dynamic Value)
{
return MyKvpHash.ContainsValue(Value);
}
public bool LacksKey(dynamic Key)
{
return !HoldsKey(Key);
}
public bool LacksValue(dynamic Value)
{
return !HoldsValue(Value);
}
public KvpHash Mirror()
{
KvpHash MyResult = new KvpHash();
MyResult.AddByIndex(new KvpHash());
MyResult.AddByIndex(new KvpHash());
foreach (DictionaryEntry my_pair in MyKvpHash)
{
if (MyResult[1].LacksKey(my_pair.Value))
{
MyResult[1].AddByKey(my_pair.Value, my_pair.Key);
}
else
{
MyResult[2].AddByKey(my_pair.Key, my_pair.Value);
}
}
return MyResult;
}
public void Remove(dynamic Key)
{
MyKvpHash.Remove(Key);
}
public void RemoveAll()
{
MyKvpHash.Clear();
}
public bool ValuesAreUnique()
{
return MyKvpHash.Count == ((dynamic[]) MyKvpHash.Values).Distinct().Count();
}
public bool ValuesAreNotUnique()
{
return !ValuesAreUnique();
}
}
}
#Freeflow if You change in Word Module the myHt definition it will by OK and will work fine.
Public Sub TestKvpHash()
Dim myHt As Object
' KvpHash is a C# wrapper for a System.Collections.HashTable
Set myHt = New VBAExtensions.KvpHash
' Rest of code
I have the following http post body sent to a asp.net web api via a web hook from chargify.
id=38347752&event=customer_update&payload[customer][address]=qreweqwrerwq&payload[customer][address_2]=qwerewrqew&payload[customer][city]=ererwqqerw&payload[customer][country]=GB&payload[customer][created_at]=2015-05-14%2004%3A46%3A48%20-0400&payload[customer][email]=a%40test.com&payload[customer][first_name]=Al&payload[customer][id]=8619620&payload[customer][last_name]=Test&payload[customer][organization]=&payload[customer][phone]=01&payload[customer][portal_customer_created_at]=2015-05-14%2004%3A46%3A49%20-0400&payload[customer][portal_invite_last_accepted_at]=&payload[customer][portal_invite_last_sent_at]=2015-05-14%2004%3A46%3A49%20-0400&payload[customer][reference]=&payload[customer][state]=&payload[customer][updated_at]=2015-05-14%2011%3A25%3A19%20-0400&payload[customer][verified]=false&payload[customer][zip]=&payload[site][id]=26911&payload[site][subdomain]=testsubdomain
How do i convert this payload[customer][address]=value etc. to a json string using c#?
You current problem
How to convert chargify webhooks to json with c#?
can be generalized to
How to extract key value pairs from a string, convert them into the corresponding hierarchy and return them in JSON?
To answer your question:
string rawData = "id=38347752&event=customer_update&payload[customer][address]=qreweqwrerwq&payload[customer][address_2]=qwerewrqew&payload[customer][city]=ererwqqerw&payload[customer][country]=GB&payload[customer][created_at]=2015-05-14%2004%3A46%3A48%20-0400&payload[customer][email]=a%40test.com&payload[customer][first_name]=Al&payload[customer][id]=8619620&payload[customer][last_name]=Test&payload[customer][organization]=&payload[customer][phone]=01&payload[customer][portal_customer_created_at]=2015-05-14%2004%3A46%3A49%20-0400&payload[customer][portal_invite_last_accepted_at]=&payload[customer][portal_invite_last_sent_at]=2015-05-14%2004%3A46%3A49%20-0400&payload[customer][reference]=&payload[customer][state]=&payload[customer][updated_at]=2015-05-14%2011%3A25%3A19%20-0400&payload[customer][verified]=false&payload[customer][zip]=&payload[site][id]=26911&payload[site][subdomain]=testsubdomain";
ChargifyWebHook webHook = new ChargifyWebHook(rawData);
JSONNode node = new JSONNode("RootOrWhatEver");
foreach (KeyValuePair<string, string> keyValuePair in webHook.KeyValuePairs)
{
node.InsertInHierarchy(ChargifyWebHook.ExtractHierarchyFromKey(keyValuePair.Key), keyValuePair.Value);
}
string result = node.ToJSONObject();
With your specified input the result looks like this (without line breaks):
{
"id": "38347752",
"event": "customer_update",
"payload": {
"customer": {
"address": "qreweqwrerwq",
"address_2": "qwerewrqew",
"city": "ererwqqerw",
"country": "GB",
"created_at": "2015-05-14 04:46:48 -0400",
"email": "a#test.com",
"first_name": "Al",
"id": "8619620",
"last_name": "Test",
"organization": "",
"phone": "01",
"portal_customer_created_at": "2015-05-14 04:46:49 -0400",
"portal_invite_last_accepted_at": "",
"portal_invite_last_sent_at": "2015-05-14 04:46:49 -0400",
"reference": "",
"state": "",
"updated_at": "2015-05-14 11:25:19 -0400",
"verified": "false",
"zip": ""
},
"site": {
"id": "26911",
"subdomain": "testsubdomain"
}
}
}
As your problem is not limited to 1, 2 or 3 levels you clearly need a recursive solution. Therefore I created a JSONNode class which is able to insert children by specifying the hierarchy as a List<string>.
If you take A.B.C as an example, at the beginning the method InsertIntoHierarchy checks whether more levels are needed or not (depending on the length of the entries specified, in our case we would get a list containing A, B and C), if so it inserts a child (used as container) with the specified name of the level and passes the problem on to this child. Of course the name of the current recursion level is removed during that step so according to our example the container with the name A would have been added and the list containing B and C would have been passed on to this container. If the last level of recursion is reached, a node containing the name and the value will be inserted.
To get the solution working you will need the following 2 classes:
ChargifyWebHook
/// <summary>
/// Represents the chargify web hook class.
/// </summary>
public class ChargifyWebHook
{
/// <summary>
/// Indicates whether the raw data has already been parsed or not.
/// </summary>
private bool initialized;
/// <summary>
/// Contains the key value pairs extracted from the raw data.
/// </summary>
private Dictionary<string, string> keyValuePairs;
/// <summary>
/// Initializes a new instance of the <see cref="ChargifyWebHook"/> class.
/// </summary>
/// <param name="data">The raw data of the web hook.</param>
/// <exception cref="System.ArgumentException">Is thrown if the sepcified raw data is null or empty.</exception>
public ChargifyWebHook(string data)
{
if (String.IsNullOrEmpty(data))
{
throw new ArgumentException("The specified value must neither be null nor empty", data);
}
this.initialized = false;
this.keyValuePairs = new Dictionary<string, string>();
this.RawData = data;
}
/// <summary>
/// Gets the raw data of the web hook.
/// </summary>
public string RawData
{
get;
private set;
}
/// <summary>
/// Gets the key value pairs contained in the raw data.
/// </summary>
public Dictionary<string, string> KeyValuePairs
{
get
{
if (!initialized)
{
this.keyValuePairs = ExtractKeyValuesFromRawData(this.RawData);
initialized = true;
}
return this.keyValuePairs;
}
}
/// <summary>
/// Extracts the key value pairs from the specified raw data.
/// </summary>
/// <param name="rawData">The data which contains the key value pairs.</param>
/// <param name="keyValuePairSeperator">The pair seperator, default is '&'.</param>
/// <param name="keyValueSeperator">The key value seperator, default is '='.</param>
/// <returns>The extracted key value pairs.</returns>
/// <exception cref="System.FormatException">Is thrown if an key value seperator is missing.</exception>
public static Dictionary<string, string> ExtractKeyValuesFromRawData(string rawData, char keyValuePairSeperator = '&', char keyValueSeperator = '=')
{
Dictionary<string, string> keyValuePairs = new Dictionary<string, string>();
string[] rawDataParts = rawData.Split(new char[] { keyValuePairSeperator });
foreach (string rawDataPart in rawDataParts)
{
string[] keyAndValue = rawDataPart.Split(new char[] { keyValueSeperator });
if (keyAndValue.Length != 2)
{
throw new FormatException("The format of the specified raw data is incorrect. Key value pairs in the following format expected: key=value or key1=value1&key2=value2...");
}
keyValuePairs.Add(Uri.UnescapeDataString(keyAndValue[0]), Uri.UnescapeDataString(keyAndValue[1]));
}
return keyValuePairs;
}
/// <summary>
/// Extracts the hierarchy from the key, e.g. A[B][C] will result in A, B and C.
/// </summary>
/// <param name="key">The key who's hierarchy shall be extracted.</param>
/// <param name="hierarchyOpenSequence">Specifies the open sequence for the hierarchy speration.</param>
/// <param name="hierarchyCloseSequence">Specifies the close sequence for the hierarchy speration.</param>
/// <returns>A list of entries for the hierarchy names.</returns>
public static List<string> ExtractHierarchyFromKey(string key, string hierarchyOpenSequence = "[", string hierarchyCloseSequence = "]")
{
if (key.Contains(hierarchyOpenSequence) && key.Contains(hierarchyCloseSequence))
{
return key.Replace(hierarchyCloseSequence, string.Empty).Split(new string[] { hierarchyOpenSequence }, StringSplitOptions.None).ToList();
}
if (key.Contains(hierarchyOpenSequence) && !key.Contains(hierarchyCloseSequence))
{
return key.Split(new string[] { hierarchyOpenSequence }, StringSplitOptions.None).ToList();
}
if (!key.Contains(hierarchyOpenSequence) && key.Contains(hierarchyCloseSequence))
{
return key.Split(new string[] { hierarchyCloseSequence }, StringSplitOptions.None).ToList();
}
return new List<string>() { key };
}
}
JSONNode
/// <summary>
/// Represents the JSONNode class.
/// </summary>
public class JSONNode
{
/// <summary>
/// Initializes a new instance of the <see cref="JSONNode"/> class.
/// </summary>
/// <param name="name">The name of the node.</param>
/// <param name="value">The value of the node.</param>
public JSONNode(string name, string value)
{
this.Name = name;
this.Value = value;
this.Children = new Dictionary<string, JSONNode>();
}
/// <summary>
/// Initializes a new instance of the <see cref="JSONNode"/> class.
/// </summary>
/// <param name="name">The name of the node.</param>
public JSONNode(string name)
: this(name, string.Empty)
{
}
/// <summary>
/// Gets the name of the node.
/// </summary>
public string Name
{
get;
private set;
}
/// <summary>
/// Gets the children of the node.
/// </summary>
public Dictionary<string, JSONNode> Children
{
get;
private set;
}
/// <summary>
/// Gets the value of the node.
/// </summary>
public string Value
{
get;
private set;
}
/// <summary>
/// Inserts a new node in the corresponding hierarchy.
/// </summary>
/// <param name="keyHierarchy">A list with entries who specify the hierarchy.</param>
/// <param name="value">The value of the node.</param>
/// <exception cref="System.ArgumentNullException">Is thrown if the keyHierarchy is null.</exception>
/// <exception cref="System.ArgumentException">Is thrown if the keyHierarchy is empty.</exception>
public void InsertInHierarchy(List<string> keyHierarchy, string value)
{
if (keyHierarchy == null)
{
throw new ArgumentNullException("keyHierarchy");
}
if (keyHierarchy.Count == 0)
{
throw new ArgumentException("The specified hierarchy list is empty", "keyHierarchy");
}
// If we are not in the correct hierarchy (at the last level), pass the problem
// to the child.
if (keyHierarchy.Count > 1)
{
// Extract the current hierarchy level as key
string key = keyHierarchy[0];
// If the key does not already exists - add it as a child.
if (!this.Children.ContainsKey(key))
{
this.Children.Add(key, new JSONNode(key));
}
// Remove the current hierarchy from the list and ...
keyHierarchy.RemoveAt(0);
// ... pass it on to the just inserted child.
this.Children[key].InsertInHierarchy(keyHierarchy, value);
return;
}
// If we are on the last level, just insert the node with it's value.
this.Children.Add(keyHierarchy[0], new JSONNode(keyHierarchy[0], value));
}
/// <summary>
/// Gets the textual representation of this node as JSON entry.
/// </summary>
/// <returns>A textual representaiton of this node as JSON entry.</returns>
public string ToJSONEntry()
{
// If there is no child, return the name and the value in JSON format.
if (this.Children.Count == 0)
{
return string.Format("\"{0}\":\"{1}\"", this.Name, this.Value);
}
// Otherwise there are childs so return all of them formatted as object.
StringBuilder builder = new StringBuilder();
builder.AppendFormat("\"{0}\":", this.Name);
builder.Append(this.ToJSONObject());
return builder.ToString();
}
/// <summary>
/// Gets the textual representation of this node as JSON object.
/// </summary>
/// <returns>A textual representaiton of this node as JSON object.</returns>
public string ToJSONObject()
{
StringBuilder builder = new StringBuilder();
builder.Append("{");
foreach (JSONNode value in this.Children.Values)
{
builder.Append(value.ToJSONEntry());
builder.Append(",");
}
builder.Remove(builder.Length - 1, 1);
builder.Append("}");
return builder.ToString();
}
}
When I try to serialize a huge object graph with DataContractSerializer, I get a StackOverFlowException. Increasing stack size to 10 MB fixes the problem in my current scenario, but of course this is not a real solution, as the object graph might be even bigger next time.
Is there any other way besides trying to flatten the data structure itself? Some parameter telling DataContractSerializer to do breadth first search? ;-) Any help is greatly appreciated. By the way, I use DataContractSerializer because it provides an easy way to keep referential integrity. Keeping this would be nice. :-)
Given that the OP is not using WCF, one possible solution would be to use XmlSerializer class. XmlSerializer can help because you have more control and you can use XmlAttributes to reduce the size of the serialized XML string.
I have developed a wrapper for XmlSerializer that uses generics that may be useful - please check the article for more details. My class can serialize to/from a string or to/from a file.
Usage:
Foo foo = ....;
string xml = XmlSerializer<Foo>.Serialize(foo);
XmlSerializer.cs
/// <summary>
/// XML serializer helper class. Serializes and deserializes objects from/to XML
/// </summary>
/// <typeparam name="T">The type of the object to serialize/deserialize.
/// Must have a parameterless constructor and implement <see cref="Serializable"/></typeparam>
public class XmlSerializer<T> where T: class, new()
{
/// <summary>
/// Deserializes a XML string into an object
/// Default encoding: <c>UTF8</c>
/// </summary>
/// <param name="xml">The XML string to deserialize</param>
/// <returns>An object of type <c>T</c></returns>
public static T Deserialize(string xml)
{
return Deserialize(xml, Encoding.UTF8, null);
}
/// <summary>
/// Deserializes a XML string into an object
/// Default encoding: <c>UTF8</c>
/// </summary>
/// <param name="xml">The XML string to deserialize</param>
/// <param name="encoding">The encoding</param>
/// <returns>An object of type <c>T</c></returns>
public static T Deserialize(string xml, Encoding encoding)
{
return Deserialize(xml, encoding, null);
}
/// <summary>
/// Deserializes a XML string into an object
/// </summary>
/// <param name="xml">The XML string to deserialize</param>
/// <param name="settings">XML serialization settings. <see cref="System.Xml.XmlReaderSettings"/></param>
/// <returns>An object of type <c>T</c></returns>
public static T Deserialize(string xml, XmlReaderSettings settings)
{
return Deserialize(xml, Encoding.UTF8, settings);
}
/// <summary>
/// Deserializes a XML string into an object
/// </summary>
/// <param name="xml">The XML string to deserialize</param>
/// <param name="encoding">The encoding</param>
/// <param name="settings">XML serialization settings. <see cref="System.Xml.XmlReaderSettings"/></param>
/// <returns>An object of type <c>T</c></returns>
public static T Deserialize(string xml, Encoding encoding, XmlReaderSettings settings)
{
if (string.IsNullOrEmpty(xml))
throw new ArgumentException("XML cannot be null or empty", "xml");
XmlSerializer xmlSerializer = new XmlSerializer(typeof(T));
using (MemoryStream memoryStream = new MemoryStream(encoding.GetBytes(xml)))
{
using (XmlReader xmlReader = XmlReader.Create(memoryStream, settings))
{
return (T) xmlSerializer.Deserialize(xmlReader);
}
}
}
/// <summary>
/// Deserializes a XML file.
/// </summary>
/// <param name="filename">The filename of the XML file to deserialize</param>
/// <returns>An object of type <c>T</c></returns>
public static T DeserializeFromFile(string filename)
{
return DeserializeFromFile(filename, new XmlReaderSettings());
}
/// <summary>
/// Deserializes a XML file.
/// </summary>
/// <param name="filename">The filename of the XML file to deserialize</param>
/// <param name="settings">XML serialization settings. <see cref="System.Xml.XmlReaderSettings"/></param>
/// <returns>An object of type <c>T</c></returns>
public static T DeserializeFromFile(string filename, XmlReaderSettings settings)
{
if (string.IsNullOrEmpty(filename))
throw new ArgumentException("filename", "XML filename cannot be null or empty");
if (! File.Exists(filename))
throw new FileNotFoundException("Cannot find XML file to deserialize", filename);
// Create the stream writer with the specified encoding
using (XmlReader reader = XmlReader.Create(filename, settings))
{
System.Xml.Serialization.XmlSerializer xmlSerializer = new System.Xml.Serialization.XmlSerializer(typeof(T));
return (T) xmlSerializer.Deserialize(reader);
}
}
/// <summary>
/// Serialize an object
/// </summary>
/// <param name="source">The object to serialize</param>
/// <returns>A XML string that represents the object to be serialized</returns>
public static string Serialize(T source)
{
// indented XML by default
return Serialize(source, null, GetIndentedSettings());
}
/// <summary>
/// Serialize an object
/// </summary>
/// <param name="source">The object to serialize</param>
/// <param name="namespaces">Namespaces to include in serialization</param>
/// <returns>A XML string that represents the object to be serialized</returns>
public static string Serialize(T source, XmlSerializerNamespaces namespaces)
{
// indented XML by default
return Serialize(source, namespaces, GetIndentedSettings());
}
/// <summary>
/// Serialize an object
/// </summary>
/// <param name="source">The object to serialize</param>
/// <param name="settings">XML serialization settings. <see cref="System.Xml.XmlWriterSettings"/></param>
/// <returns>A XML string that represents the object to be serialized</returns>
public static string Serialize(T source, XmlWriterSettings settings)
{
return Serialize(source, null, settings);
}
/// <summary>
/// Serialize an object
/// </summary>
/// <param name="source">The object to serialize</param>
/// <param name="namespaces">Namespaces to include in serialization</param>
/// <param name="settings">XML serialization settings. <see cref="System.Xml.XmlWriterSettings"/></param>
/// <returns>A XML string that represents the object to be serialized</returns>
public static string Serialize(T source, XmlSerializerNamespaces namespaces, XmlWriterSettings settings)
{
if (source == null)
throw new ArgumentNullException("source", "Object to serialize cannot be null");
string xml = null;
XmlSerializer serializer = new XmlSerializer(source.GetType());
using (MemoryStream memoryStream = new MemoryStream())
{
using (XmlWriter xmlWriter = XmlWriter.Create(memoryStream, settings))
{
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(typeof(T));
x.Serialize(xmlWriter, source, namespaces);
memoryStream.Position = 0; // rewind the stream before reading back.
using (StreamReader sr = new StreamReader(memoryStream))
{
xml = sr.ReadToEnd();
}
}
}
return xml;
}
/// <summary>
/// Serialize an object to a XML file
/// </summary>
/// <param name="source">The object to serialize</param>
/// <param name="filename">The file to generate</param>
public static void SerializeToFile(T source, string filename)
{
// indented XML by default
SerializeToFile(source, filename, null, GetIndentedSettings());
}
/// <summary>
/// Serialize an object to a XML file
/// </summary>
/// <param name="source">The object to serialize</param>
/// <param name="filename">The file to generate</param>
/// <param name="namespaces">Namespaces to include in serialization</param>
public static void SerializeToFile(T source, string filename, XmlSerializerNamespaces namespaces)
{
// indented XML by default
SerializeToFile(source, filename, namespaces, GetIndentedSettings());
}
/// <summary>
/// Serialize an object to a XML file
/// </summary>
/// <param name="source">The object to serialize</param>
/// <param name="filename">The file to generate</param>
/// <param name="settings">XML serialization settings. <see cref="System.Xml.XmlWriterSettings"/></param>
public static void SerializeToFile(T source, string filename, XmlWriterSettings settings)
{
SerializeToFile(source, filename, null, settings);
}
/// <summary>
/// Serialize an object to a XML file
/// </summary>
/// <param name="source">The object to serialize</param>
/// <param name="filename">The file to generate</param>
/// <param name="namespaces">Namespaces to include in serialization</param>
/// <param name="settings">XML serialization settings. <see cref="System.Xml.XmlWriterSettings"/></param>
public static void SerializeToFile(T source, string filename, XmlSerializerNamespaces namespaces, XmlWriterSettings settings)
{
if (source == null)
throw new ArgumentNullException("source", "Object to serialize cannot be null");
XmlSerializer serializer = new XmlSerializer(source.GetType());
using (XmlWriter xmlWriter = XmlWriter.Create(filename, settings))
{
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(typeof(T));
x.Serialize(xmlWriter, source, namespaces);
}
}
#region Private methods
private static XmlWriterSettings GetIndentedSettings()
{
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
xmlWriterSettings.Indent = true;
xmlWriterSettings.IndentChars = "\t";
return xmlWriterSettings;
}
#endregion
}
I have a C# class that I have inherited. I have successfully "built" the object. But I need to serialize the object to XML. Is there an easy way to do it?
It looks like the class has been set up for serialization, but I'm not sure how to get the XML representation. My class definition looks like this:
[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.domain.com/test")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.domain.com/test", IsNullable = false)]
public partial class MyObject
{
...
}
Here is what I thought I could do, but it doesn't work:
MyObject o = new MyObject();
// Set o properties
string xml = o.ToString();
How do I get the XML representation of this object?
You have to use XmlSerializer for XML serialization. Below is a sample snippet.
XmlSerializer xsSubmit = new XmlSerializer(typeof(MyObject));
var subReq = new MyObject();
var xml = "";
using(var sww = new StringWriter())
{
using(XmlWriter writer = XmlWriter.Create(sww))
{
xsSubmit.Serialize(writer, subReq);
xml = sww.ToString(); // Your XML
}
}
As per #kiquenet request for generic class:
public class MySerializer<T> where T : class
{
public static string Serialize(T obj)
{
XmlSerializer xsSubmit = new XmlSerializer(typeof(T));
using (var sww = new StringWriter())
{
using (XmlTextWriter writer = new XmlTextWriter(sww) { Formatting = Formatting.Indented })
{
xsSubmit.Serialize(writer, obj);
return sww.ToString();
}
}
}
}
usage:
string xmlMessage = MySerializer<MyClass>.Serialize(myObj);
I modified mine to return a string rather than use a ref variable like below.
public static string Serialize<T>(this T value)
{
if (value == null)
{
return string.Empty;
}
try
{
var xmlserializer = new XmlSerializer(typeof(T));
var stringWriter = new StringWriter();
using (var writer = XmlWriter.Create(stringWriter))
{
xmlserializer.Serialize(writer, value);
return stringWriter.ToString();
}
}
catch (Exception ex)
{
throw new Exception("An error occurred", ex);
}
}
Its usage would be like this:
var xmlString = obj.Serialize();
The following function can be copied to any object to add an XML save function using the System.Xml namespace.
/// <summary>
/// Saves to an xml file
/// </summary>
/// <param name="FileName">File path of the new xml file</param>
public void Save(string FileName)
{
using (var writer = new System.IO.StreamWriter(FileName))
{
var serializer = new XmlSerializer(this.GetType());
serializer.Serialize(writer, this);
writer.Flush();
}
}
To create the object from the saved file, add the following function and replace [ObjectType] with the object type to be created.
/// <summary>
/// Load an object from an xml file
/// </summary>
/// <param name="FileName">Xml file name</param>
/// <returns>The object created from the xml file</returns>
public static [ObjectType] Load(string FileName)
{
using (var stream = System.IO.File.OpenRead(FileName))
{
var serializer = new XmlSerializer(typeof([ObjectType]));
return serializer.Deserialize(stream) as [ObjectType];
}
}
Extension class:
using System.IO;
using System.Xml;
using System.Xml.Serialization;
namespace MyProj.Extensions
{
public static class XmlExtension
{
public static string Serialize<T>(this T value)
{
if (value == null) return string.Empty;
var xmlSerializer = new XmlSerializer(typeof(T));
using (var stringWriter = new StringWriter())
{
using (var xmlWriter = XmlWriter.Create(stringWriter,new XmlWriterSettings{Indent = true}))
{
xmlSerializer.Serialize(xmlWriter, value);
return stringWriter.ToString();
}
}
}
}
}
Usage:
Foo foo = new Foo{MyProperty="I have been serialized"};
string xml = foo.Serialize();
Just reference the namespace holding your extension method in the file you would like to use it in and it'll work (in my example it would be: using MyProj.Extensions;)
Note that if you want to make the extension method specific to only a particular class(eg., Foo), you can replace the T argument in the extension method, eg.
public static string Serialize(this Foo value){...}
You can use the function like below to get serialized XML from any object.
public static bool Serialize<T>(T value, ref string serializeXml)
{
if (value == null)
{
return false;
}
try
{
XmlSerializer xmlserializer = new XmlSerializer(typeof(T));
StringWriter stringWriter = new StringWriter();
XmlWriter writer = XmlWriter.Create(stringWriter);
xmlserializer.Serialize(writer, value);
serializeXml = stringWriter.ToString();
writer.Close();
return true;
}
catch (Exception ex)
{
return false;
}
}
You can call this from the client.
All upvoted answers above are correct. This is just simplest version:
private string Serialize(Object o)
{
using (var writer = new StringWriter())
{
new XmlSerializer(o.GetType()).Serialize(writer, o);
return writer.ToString();
}
}
To serialize an object, do:
using (StreamWriter myWriter = new StreamWriter(path, false))
{
XmlSerializer mySerializer = new XmlSerializer(typeof(your_object_type));
mySerializer.Serialize(myWriter, objectToSerialize);
}
Also remember that for XmlSerializer to work, you need a parameterless constructor.
I will start with the copy answer of Ben Gripka:
public void Save(string FileName)
{
using (var writer = new System.IO.StreamWriter(FileName))
{
var serializer = new XmlSerializer(this.GetType());
serializer.Serialize(writer, this);
writer.Flush();
}
}
I used this code earlier. But reality showed that this solution is a bit problematic. Usually most of programmers just serialize setting on save and deserialize settings on load. This is an optimistic scenario. Once the serialization failed, because of some reason, the file is partly written, XML file is not complete and it is invalid. In consequence XML deserialization does not work and your application may crash on start. If the file is not huge, I suggest first serialize object to MemoryStream then write the stream to the File. This case is especially important if there is some complicated custom serialization. You can never test all cases.
public void Save(string fileName)
{
//first serialize the object to memory stream,
//in case of exception, the original file is not corrupted
using (MemoryStream ms = new MemoryStream())
{
var writer = new System.IO.StreamWriter(ms);
var serializer = new XmlSerializer(this.GetType());
serializer.Serialize(writer, this);
writer.Flush();
//if the serialization succeed, rewrite the file.
File.WriteAllBytes(fileName, ms.ToArray());
}
}
The deserialization in real world scenario should count with corrupted serialization file, it happens sometime. Load function provided by Ben Gripka is fine.
public static [ObjectType] Load(string fileName)
{
using (var stream = System.IO.File.OpenRead(fileName))
{
var serializer = new XmlSerializer(typeof([ObjectType]));
return serializer.Deserialize(stream) as [ObjectType];
}
}
And it could be wrapped by some recovery scenario. It is suitable for settings files or other files which can be deleted in case of problems.
public static [ObjectType] LoadWithRecovery(string fileName)
{
try
{
return Load(fileName);
}
catch(Excetion)
{
File.Delete(fileName); //delete corrupted settings file
return GetFactorySettings();
}
}
It's a little bit more complicated than calling the ToString method of the class, but not much.
Here's a simple drop-in function you can use to serialize any type of object. It returns a string containing the serialized XML contents:
public string SerializeObject(object obj)
{
System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(obj.GetType());
using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) {
serializer.Serialize(ms, obj);
ms.Position = 0;
xmlDoc.Load(ms);
return xmlDoc.InnerXml;
}
}
Based on above solutions, here comes a extension class which you can use to serialize and deserialize any object. Any other XML attributions are up to you.
Just use it like this:
string s = new MyObject().Serialize(); // to serialize into a string
MyObject b = s.Deserialize<MyObject>();// deserialize from a string
internal static class Extensions
{
public static T Deserialize<T>(this string value)
{
var xmlSerializer = new XmlSerializer(typeof(T));
return (T)xmlSerializer.Deserialize(new StringReader(value));
}
public static string Serialize<T>(this T value)
{
if (value == null)
return string.Empty;
var xmlSerializer = new XmlSerializer(typeof(T));
using (var stringWriter = new StringWriter())
{
using (var xmlWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings { Indent = true }))
{
xmlSerializer.Serialize(xmlWriter, value);
return stringWriter.ToString();
}
}
}
}
I have a simple way to serialize an object to XML using C#, it works great and it's highly reusable. I know this is an older thread, but I wanted to post this because someone may find this helpful to them.
Here is how I call the method:
var objectToSerialize = new MyObject();
var xmlString = objectToSerialize.ToXmlString();
Here is the class that does the work:
Note: Since these are extension methods they need to be in a static class.
using System.IO;
using System.Xml.Serialization;
public static class XmlTools
{
public static string ToXmlString<T>(this T input)
{
using (var writer = new StringWriter())
{
input.ToXml(writer);
return writer.ToString();
}
}
private static void ToXml<T>(this T objectToSerialize, StringWriter writer)
{
new XmlSerializer(typeof(T)).Serialize(writer, objectToSerialize);
}
}
Here is a good tutorial on how to do this
You should basically use System.Xml.Serialization.XmlSerializer class to do this.
my work code. Returns utf8 xml enable empty namespace.
// override StringWriter
public class Utf8StringWriter : StringWriter
{
public override Encoding Encoding => Encoding.UTF8;
}
private string GenerateXmlResponse(Object obj)
{
Type t = obj.GetType();
var xml = "";
using (StringWriter sww = new Utf8StringWriter())
{
using (XmlWriter writer = XmlWriter.Create(sww))
{
var ns = new XmlSerializerNamespaces();
// add empty namespace
ns.Add("", "");
XmlSerializer xsSubmit = new XmlSerializer(t);
xsSubmit.Serialize(writer, obj, ns);
xml = sww.ToString(); // Your XML
}
}
return xml;
}
Example returns response Yandex api payment Aviso url:
<?xml version="1.0" encoding="utf-8"?><paymentAvisoResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" performedDatetime="2017-09-01T16:22:08.9747654+07:00" code="0" shopId="54321" invoiceId="12345" orderSumAmount="10643" />
string FilePath = ConfigurationReader.FileLocation; //Getting path value from web.config
XmlSerializer serializer = new XmlSerializer(typeof(Devices)); //typeof(object)
MemoryStream memStream = new MemoryStream();
serializer.Serialize(memStream, lstDevices);//lstdevices : I take result as a list.
FileStream file = new FileStream(folderName + "\\Data.xml", FileMode.Create, FileAccess.ReadWrite); //foldername:Specify the path to store the xml file
memStream.WriteTo(file);
file.Close();
You can create and store the result as xml file in the desired location.
Or you can add this method to your object:
public void Save(string filename)
{
var ser = new XmlSerializer(this.GetType());
using (var stream = new FileStream(filename, FileMode.Create))
ser.Serialize(stream, this);
}
Here's a basic code that will help serializing the C# objects into xml:
using System;
public class clsPerson
{
public string FirstName;
public string MI;
public string LastName;
}
class class1
{
static void Main(string[] args)
{
clsPerson p=new clsPerson();
p.FirstName = "Jeff";
p.MI = "A";
p.LastName = "Price";
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(p.GetType());
x.Serialize(Console.Out, p);
Console.WriteLine();
Console.ReadLine();
}
}
public string ObjectToXML(object input)
{
try
{
var stringwriter = new System.IO.StringWriter();
var serializer = new XmlSerializer(input.GetType());
serializer.Serialize(stringwriter, input);
return stringwriter.ToString();
}
catch (Exception ex)
{
if (ex.InnerException != null)
ex = ex.InnerException;
return "Could not convert: " + ex.Message;
}
}
//Usage
var res = ObjectToXML(obj)
You need to use following classes:
using System.IO;
using System.Xml;
using System.Xml.Serialization;
Here is a generic object serializer:
using System.IO;
using System.Text;
using System.Xml.Schema;
namespace System.Xml.Serialization
{
/// <summary>
/// Serializes and deserializes <typeparamref name="T"/> objects into XML documents.
/// Allows you to control the process of encoding objects in XML.
/// </summary>
/// <typeparam name="T">Object type.</typeparam>
public static class XmlSerializer<T>
{
private static readonly XmlSerializer _serializer = new XmlSerializer(typeof(T));
private static readonly XmlWriterSettings _defaultWriterSettings = new XmlWriterSettings
{
CheckCharacters = false
CloseOutput=false
ConformanceLevel = ConformanceLevel.Auto,
Encoding = Encoding.UTF8,
indent=true,
IndentChars = "\t",
NamespaceHandling = NamespaceHandling.OmitDuplicates,
NewLineChars = "\r\n",
NewLineHandling = NewLineHandling.Replace,
NewLineOnAttributes = false,
OmitXmlDeclaration = false
};
private static readonly XmlReaderSettings _defaultReaderSettings = new XmlReaderSettings
{
CheckCharacters = false
CloseInput=false
ConformanceLevel = ConformanceLevel.Auto,
DtdProcessing = DtdProcessing.Prohibit,
IgnoreComments = true,
IgnoreProcessingInstructions = true,
IgnoreWhitespace=true,
LineNumberOffset = 0
LinePositionOffset = 0
MaxCharactersFromEntities = 0,
MaxCharactersInDocument = 0,
NameTable = null
// Schemas = null, // ???
ValidationFlags = XmlSchemaValidationFlags.None,
ValidationType = ValidationType. None,
XmlResolver = null
};
/// <summary>
/// Default character encoding.
/// </summary>
public static Encoding DefaultEncoding => Encoding.UTF8;
/// <summary>
/// Default settings for the <see cref="XmlWriter" /> instance being created.
/// </summary>
public static XmlWriterSettings DefaultXmlWriterSettings => _defaultWriterSettings.Clone();
/// <summary>
/// Default settings for the <see cref="XmlReader" /> instance that is created.
/// </summary>
public static XmlReaderSettings DefaultXmlReaderSettings => _defaultReaderSettings.Clone();
/// <summary>
/// Serializes the given <typeparamref name="T"/> and returns the XML document as a string.
/// </summary>
/// <param name="o">
/// Instance <see cref="object" /> to serialize.
/// </param>
public static string Serialize(T o)
{
StringBuilder sb = new StringBuilder();
using (XmlWriter xmlWriter = XmlWriter.Create(sb))
_serializer.Serialize(xmlWriter, o, (XmlSerializerNamespaces)null);
return sb.ToString();
}
/// <summary>
/// Serializes the given <typeparamref name="T"/> and returns the XML document as a string.
/// </summary>
/// <param name="o">
/// Instance <see cref="object" /> to serialize.
/// </param>
/// <param name="settings">
/// Settings for the new <see cref="XmlWriter" /> instance. If <see langword="null"/> is specified,
/// settings are used <see cref="DefaultXmlWriterSettings"/>.
/// </param>
public static string Serialize(T o, XmlWriterSettings settings)
{
if (settings == null) settings = _defaultWriterSettings;
StringBuilder sb = new StringBuilder();
using (XmlWriter xmlWriter = XmlWriter.Create(sb, settings))
_serializer.Serialize(xmlWriter, o, (XmlSerializerNamespaces)null);
return sb.ToString();
}
/// <summary>
/// Serializes the given <typeparamref name="T"/> and writes the XML document to a file using the given <see cref="TextWriter" />.
/// </summary>
/// <param name="textWriter">
/// <see cref="TextWriter" /> Used to write an XML document.
/// </param>
/// <param name="o">
/// Instance <see cref="object" /> to serialize.
/// </param>
public static void Serialize(TextWriter textWriter, T o)
{
using (XmlWriter xmlWriter = XmlWriter.Create(textWriter))
_serializer.Serialize(textWriter, o, (XmlSerializerNamespaces)null);
}
/// <summary>
/// Serializes the given <typeparamref name="T"/> and writes the XML document to a file using the given <see cref="TextWriter" />.
/// </summary>
/// <param name="textWriter">
/// <see cref="TextWriter" /> Used to write an XML document.
/// </param>
/// <param name="o">
/// Instance <see cref="object" /> to serialize.
/// </param>
/// <param name="settings">
/// Settings for the new <see cref="XmlWriter" /> instance. If <see langword="null"/> is specified,
/// settings are used <see cref="DefaultXmlWriterSettings"/>.
/// </param>
public static void Serialize(TextWriter textWriter, T o, XmlWriterSettings settings)
{
if (settings == null) settings = _defaultWriterSettings;
using (XmlWriter xmlWriter = XmlWriter.Create(textWriter, settings))
_serializer.Serialize(xmlWriter, o, (XmlSerializerNamespaces)null);
}
/// <summary>
/// Serializes the given <typeparamref name="T"/> and writes the XML document to a file using the given <see cref="TextWriter" /> and references to the given namespaces.
/// </summary>
/// <param name="textWriter">
/// <see cref="TextWriter" /> Used to write an XML document.
/// </param>
/// <param name="o">
/// Instance <see cref="object" /> to serialize.
/// </param>
/// <param name="namespaces">
/// <see cref="XmlSerializerNamespaces" /> Contains the namespaces for the generated XML document.
/// </param>
/// <exception cref="InvalidOperationException">
/// An error occurred during serialization.
/// The original exception is accessible using the <see cref="P:System.Exception.InnerException" /> property.
/// </exception>
public static void Serialize(TextWriter textWriter, T o, XmlSerializerNamespaces namespaces)
{
using (XmlWriter xmlWriter = XmlWriter.Create(textWriter))
_serializer.Serialize(xmlWriter, o, namespaces);
}
/// <summary>
/// Serializes the given <typeparamref name="T"/> and writes the XML document to a file using the given <see cref="TextWriter" /> and references to the given namespaces.
/// </summary>
/// <param name="textWriter">
/// <see cref="TextWriter" /> Used to write an XML document.
/// </param>
/// <param name="o">
/// Instance <see cref="object" /> to serialize.
/// </param>
/// <param name="namespaces">
/// <see cref="XmlSerializerNamespaces" /> Contains the namespaces for the generated XML document.
/// </param>
/// <param name="settings">
/// Settings for the new <see cref="XmlWriter" /> instance. If <see langword="null"/> is specified,
/// settings are used <see cref="DefaultXmlWriterSettings"/>.
/// </param>
/// <exception cref="InvalidOperationException">
/// An error occurred during serialization.
/// The original exception is accessible using the <see cref="P:System.Exception.InnerException" /> property.
/// </exception>
public static void Serialize(TextWriter textWriter, T o, XmlSerializerNamespaces namespaces, XmlWriterSettings settings)
{
if (settings == null) settings = _defaultWriterSettings;
using (XmlWriter xmlWriter = XmlWriter.Create(textWriter, settings))
_serializer.Serialize(xmlWriter, o, namespaces);
}
/// <summary>
/// Serializes the given <typeparamref name="T"/> and writes the XML document to a file using the given <see cref="Stream" />.
/// </summary>
/// <param name="stream">
/// <see cref="Stream" /> Used to write an XML document.
/// </param>
/// <param name="o">
/// Instance <see cref="object" /> to serialize.
/// </param>
/// <exception cref="InvalidOperationException">
/// An error occurred during serialization.
/// The original exception is accessible using the <see cref="P:System.Exception.InnerException" /> property.
/// </exception>
public static void Serialize(Stream stream, T o)
{
_serializer.Serialize(stream, o, (XmlSerializerNamespaces)null);
}
/// <summary>
/// Serializes the given <typeparamref name="T"/> and writes the XML document to a file using the given <see cref="Stream" />.
/// </summary>
/// <param name="stream">
/// <see cref="Stream" /> Used to write an XML document.
/// </param>
/// <param name="o">
/// Instance <see cref="object" /> to serialize.
/// </param>
/// <param name="settings">
/// Settings for the new <see cref="XmlWriter" /> instance. If <see langword="null"/> is specified,
/// settings are used <see cref="DefaultXmlWriterSettings"/>.
/// </param>
/// <exception cref="InvalidOperationException">
/// An error occurred during serialization.
/// The original exception is accessible using the <see cref="P:System.Exception.InnerException" /> property.
/// </exception>
public static void Serialize(Stream stream, T o, XmlWriterSettings settings)
{
if (settings == null) settings = _defaultWriterSettings;
using (TextWriter writer = new StreamWriter(stream, settings.Encoding))
using (XmlWriter xmlWriter = XmlWriter.Create(writer, settings))
_serializer.Serialize(xmlWriter, o, (XmlSerializerNamespaces) null);
}
/// <summary>
/// Serializes the given <typeparamref name="T"/> and writes the XML document to a file using the given <see cref="Stream" /> refers to the given namespaces.
/// </summary>
/// <param name="stream">
/// <see cref="Stream" /> Used to write an XML document.
/// </param>
/// <param name="o">
/// Instance <see cref="object" /> to serialize.
/// </param>
/// <param name="namespaces">
/// <see cref="XmlSerializerNamespaces" /> The object is referenced.
/// </param>
/// <exception cref="InvalidOperationException">
/// An error occurred during serialization.
/// The original exception is accessible using the <see cref="P:System.Exception.InnerException" /> property.
/// </exception>
public static void Serialize(Stream stream, T o, XmlSerializerNamespaces namespaces)
{
_serializer.Serialize(stream, o, namespaces);
}
/// <summary>
/// Serializes the given <typeparamref name="T"/> and writes the XML document to a file using the given <see cref="Stream" /> refers to the given namespaces.
/// </summary>
/// <param name="stream">
/// <see cref="Stream" /> Used to write an XML document.
/// </param>
/// <param name="o">
/// Instance <see cref="object" /> to serialize.
/// </param>
/// <param name="namespaces">
/// <see cref="XmlSerializerNamespaces" /> The object is referenced.
/// </param>
/// <param name="settings">
/// Settings for the new <see cref="XmlWriter" /> instance. If <see langword="null"/> is specified,
/// settings are used <see cref="DefaultXmlWriterSettings"/>.
/// </param>
/// <exception cref="InvalidOperationException">
/// An error occurred during serialization.
/// The original exception is accessible using the <see cref="P:System.Exception.InnerException" /> property.
/// </exception>
public static void Serialize(Stream stream, T o, XmlSerializerNamespaces namespaces, XmlWriterSettings settings)
{
if (settings == null) settings = _defaultWriterSettings;
using (TextWriter writer = new StreamWriter(stream, settings.Encoding))
using (XmlWriter xmlWriter = XmlWriter.Create(writer, settings))
_serializer.Serialize(xmlWriter, o, namespaces);
}
/// <summary>
/// Serializes the given <typeparamref name="T"/> and writes the XML document to a file using the given <see cref="XmlWriter" />.
/// </summary>
/// <param name="xmlWriter">
/// <see cref="XmlWriter" /> Used to write an XML document.
/// </param>
/// <param name="o">
/// Instance <see cref="object" /> to serialize.
/// </param>
/// <param name="settings">
/// Settings for the new <see cref="XmlWriter" /> instance. If <see langword="null"/> is specified,
/// the settings of the current <see cref="XmlWriter" /> instance are used.
/// </param>
/// <exception cref="InvalidOperationException">
/// An error occurred during serialization.
/// The original exception is accessible using the <see cref="P:System.Exception.InnerException" /> property.
/// </exception>
public static void Serialize(XmlWriter xmlWriter, T o, XmlWriterSettings settings = null)
{
using (XmlWriter writer = settings == null ? xmlWriter : XmlWriter.Create(xmlWriter, settings))
_serializer.Serialize(writer, o, (XmlSerializerNamespaces)null);
}
/// <summary>
/// Serializes the given <typeparamref name="T"/> and writes the XML document to a file using the given <see cref="XmlWriter" /> and references to the given namespaces.
/// </summary>
/// <param name="xmlWriter">
/// <see cref="XmlWriter" /> Used to write an XML document.
/// </param>
/// <param name="o">
/// Instance <see cref="object" /> to serialize.
/// </param>
/// <param name="namespaces">
/// <see cref="XmlSerializerNamespaces" /> The object is referenced.
/// </param>
/// <param name="settings">
/// Settings for the new <see cref="XmlWriter" /> instance. If <see langword="null"/> is specified,
/// the settings of the current <see cref="XmlWriter" /> instance are used.
/// </param>
/// <exception cref="InvalidOperationException">
/// An error occurred during serialization.
/// The original exception is accessible using the <see cref="P:System.Exception.InnerException" /> property.
/// </exception>
public static void Serialize(XmlWriter xmlWriter, T o, XmlSerializerNamespaces namespaces, XmlWriterSettings settings = null)
{
using (XmlWriter writer = settings == null ? xmlWriter : XmlWriter.Create(xmlWriter, settings))
_serializer.Serialize(writer, o, namespaces);
}
/// <summary>
/// Serializes the specified object and writes the XML document to a file using the specified <typeparamref name="T"/> and references the specified namespaces and encoding style.
/// </summary>
/// <param name="xmlWriter">
/// <see cref="XmlWriter" /> Used to write an XML document.
/// </param>
/// <param name="o">Object to serialize.</param>
/// <param name="namespaces">
/// <see cref="XmlSerializerNamespaces" /> The object is referenced.
/// </param>
/// <param name="encodingStyle">
/// The encoding style of the serialized XML.
/// </param>
/// <param name="settings">
/// Settings for the new <see cref="XmlWriter" /> instance. If <see langword="null"/> is specified,
/// the settings of the current <see cref="XmlWriter" /> instance are used.
/// </param>
/// <exception cref="InvalidOperationException">
/// An error occurred during serialization.
/// The original exception is accessible using the <see cref="P:System.Exception.InnerException" /> property.
/// </exception>
public static void Serialize(
XmlWriter xmlWriter,
T o
XmlSerializerNamespaces,
string encodingStyle,
XmlWriterSettings settings = null)
{
using (XmlWriter writer = settings == null ? xmlWriter : XmlWriter.Create(xmlWriter, settings))
_serializer.Serialize(writer, o, namespaces, encodingStyle, (string)null);
}
/// <summary>
/// Serializes the given <typeparamref name="T"/> and writes the XML document to a file using the given <see cref="XmlWriter" />, XML namespaces, and encoding.
/// </summary>
/// <param name="xmlWriter">
/// <see cref="XmlWriter" /> Used to write an XML document.
/// </param>
/// <param name="o">Object to serialize.</param>
/// <param name="namespaces">
/// An instance of <see langword="XmlSerializaerNamespaces" /> containing the namespaces and prefixes used.
/// </param>
/// <param name="encodingStyle">
/// The encoding used in the document.
/// </param>
/// <param name="id">
/// For SOAP encoded messages, a base is used to generate identifier attributes.
/// </param>
/// <param name="settings">
/// Settings for the new <see cref="XmlWriter" /> instance. If <see langword="null"/> is specified,
/// the settings of the current <see cref="XmlWriter" /> instance are used.
/// </param>
public static void Serialize(
XmlWriter xmlWriter,
T o
XmlSerializerNamespaces,
string encodingStyle,
string id,
XmlWriterSettings settings = null)
{
using (XmlWriter writer = settings == null ? xmlWriter : XmlWriter.Create(xmlWriter, settings))
_serializer.Serialize(writer, o, namespaces, encodingStyle, id);
}
/// <summary>
/// Deserializes the XML document contained in the specified string.
/// </summary>
/// settings are used <see cref="DefaultXmlReaderSettings"/>.</param>
/// <returns> The deserialized object <typeparamref name="T"/>. </returns>
public static T Deserialize(string text)
{
using (StringReader reader = new StringReader(text))
using (XmlReader xmlReader = XmlReader.Create(reader))
return (T)_serializer.Deserialize(xmlReader);
}
/// <summary>
/// Deserializes the XML document contained in the specified string.
/// </summary>
/// <param name="text">String containing the XML document.</param>
/// <param name="settings"> Settings for the new <see cref="XmlReader" /> instance. If <see langword="null"/> is specified,
/// settings are used <see cref="DefaultXmlReaderSettings"/>.</param>
/// <returns> The deserialized object <typeparamref name="T"/>. </returns>
public static T Deserialize(string text, XmlReaderSettings settings)
{
if (settings == null) settings = _defaultReaderSettings;
using (StringReader reader = new StringReader(text))
using (XmlReader xmlReader = XmlReader.Create(reader, settings))
return (T)_serializer.Deserialize(xmlReader);
}
/// <summary>
/// Deserializes the XML document contained in the specified <see cref="Stream" />.
/// </summary>
/// <param name="stream">
/// <see cref="Stream" /> Containing the XML document to deserialize.
/// </param>
/// <returns>
/// Deserialized object <typeparamref name="T"/>.
/// </returns>
public static T Deserialize(Stream stream)
{
return (T)_serializer.Deserialize(stream);
}
/// <summary>
/// Deserializes the XML document contained in the specified <see cref="Stream" />.
/// </summary>
/// <param name="stream">
/// <see cref="Stream" /> Containing the XML document to deserialize.
/// </param>
/// <param name="settings">Settings for the new <see cref="XmlReader" /> instance. If <see langword="null"/> is specified,
/// settings are used <see cref="DefaultXmlReaderSettings"/>.</param>
/// <returns>
/// Deserialized object <typeparamref name="T"/>.
/// </returns>
public static T Deserialize(Stream stream, XmlReaderSettings settings)
{
if (settings == null) settings = _defaultReaderSettings;
using(XmlReader xmlReader = XmlReader.Create(stream, settings))
return (T)_serializer.Deserialize(xmlReader);
}
/// <summary>
/// Deserializes the XML document contained in the specified <see cref="TextReader" />.
/// </summary>
/// <param name="textReader">
/// <see cref="TextReader" /> The containing XML document to deserialize.
/// </param>
/// <returns>
/// Deserialized object <typeparamref name="T"/>.
/// </returns>
/// <exception cref="InvalidOperationException">
/// An error occurred during deserialization.
/// The original exception is accessible using the <see cref="P:System.Exception.InnerException" /> property.
/// </exception>
public static T Deserialize(TextReader textReader)
{
return (T) _serializer.Deserialize(textReader);
}
/// <summary>
/// Deserializes the XML document contained in the specified <see cref="TextReader" />.
/// </summary>
/// <param name="textReader">
/// <see cref="TextReader" /> The containing XML document to deserialize.
/// </param>
/// <param name="settings">Settings for the new <see cref="XmlReader" /> instance. If <see langword="null"/> is specified,
/// settings are used <see cref="DefaultXmlReaderSettings"/>.</param>
/// <returns>
/// Deserialized object <typeparamref name="T"/>.
/// </returns>
/// <exception cref="InvalidOperationException">
/// An error occurred during deserialization.
/// The original exception is accessible using the <see cref="P:System.Exception.InnerException" /> property.
/// </exception>
public static T Deserialize(TextReader textReader, XmlReaderSettings settings)
{
if (settings == null) settings = _defaultReaderSettings;
using (XmlReader xmlReader = XmlReader.Create(textReader, settings))
return (T)_serializer.Deserialize(xmlReader);
}
/// <summary>
/// Deserializes the XML document contained in the specified <see cref="XmlReader" />.
/// </summary>
/// <param name="xmlReader">
/// <see cref="XmlReader" /> The containing XML document to deserialize.
/// </param>
/// <param name="settings">Settings for the new <see cref="XmlReader" /> instance. If <see langword="null"/> is specified,
/// current instance settings are used <see cref="XmlReader" />.</param>
/// <returns>
/// Deserialized object <typeparamref name="T"/>.
/// </returns>
/// <exception cref="InvalidOperationException">
/// An error occurred during deserialization.
/// The original exception is accessible using the <see cref="P:System.Exception.InnerException" /> property.
/// </exception>
public static T Deserialize(XmlReader xmlReader, XmlReaderSettings settings = null)
{
using (XmlReader reader = settings == null ? xmlReader : XmlReader.Create(xmlReader, settings))
return (T)_serializer.Deserialize(xmlReader);
}
/// <summary>
/// Deserializes the XML document contained in the specified <see cref="XmlReader" /> and allows you to override events that occur during deserialization.
/// </summary>
/// <param name="xmlReader">
/// <see cref="XmlReader" /> The containing document to deserialize.
/// </param>
/// <param name="events">
/// Class instance <see cref="XmlDeserializationEvents" />.
/// </param>
/// <param name="settings">Settings for the new <see cref="XmlReader" /> instance. If <see langword="null"/> is specified,
/// current instance settings are used <see cref="XmlReader" />.</param>
/// <returns>
/// Deserialized object <typeparamref name="T"/>.
/// </returns>
public static T Deserialize(XmlReader xmlReader, XmlDeserializationEvents events, XmlReaderSettings settings = null)
{
using (XmlReader reader = settings == null ? xmlReader : XmlReader.Create(xmlReader, settings))
return (T)_serializer.Deserialize(reader, (string)null, events);
}
/// <summary>
/// Deserializes the XML document contained in the specified <see cref="XmlReader" /> and encoding style.
/// </summary>
/// <param name="xmlReader">
/// <see cref="XmlReader" /> The containing XML document to deserialize.
/// </param>
/// <param name="encodingStyle">
/// The encoding style of the serialized XML.
/// </param>
/// <param name="settings">Settings for the new <see cref="XmlReader" /> instance. If <see langword="null"/> is specified,
/// current instance settings are used <see cref="XmlReader" />.</param>
/// <returns>The deserialized object.</returns>
/// <exception cref="InvalidOperationException">
/// An error occurred during deserialization.
/// The original exception is accessible using the <see cref="P:System.Exception.InnerException" /> property.
/// </exception>
public static T Deserialize(XmlReader xmlReader, string encodingStyle, XmlReaderSettings settings = null)
{
using (XmlReader reader = settings == null ? xmlReader : XmlReader.Create(xmlReader, settings))
return (T)_serializer.Deserialize(reader, encodingStyle);
}
/// <summary>
/// Deserializes the object using the data contained in the specified <see cref="XmlReader" />.
/// </summary>
/// <param name="xmlReader">
/// An instance of the <see cref="XmlReader" /> class used to read the document.
/// </param>
/// <param name="encodingStyle">Encoding used.</param>
/// <param name="events">
/// Class instance <see cref="XmlDeserializationEvents" />.
/// </param>
/// <param name="settings">Settings for the new <see cref="XmlReader" /> instance. If <see langword="null"/> is specified,
/// current instance settings are used <see cref="XmlReader" />.</param>
/// <returns>The deserialized object <typeparamref name="T"/>.</returns>
public static object Deserialize(
xmlReader xmlReader,
string encodingStyle,
XmlDeserializationEvents events,
XmlReaderSettings settings = null)
{
using (XmlReader reader = settings == null ? xmlReader : XmlReader.Create(xmlReader, settings))
return _serializer.Deserialize(reader, encodingStyle, events);
}
/// <summary>
/// Returns a value indicating whether this <see cref="XmlSerializer" /> can deserialize the specified XML document.
/// </summary>
/// <param name="xmlReader">
/// <see cref="XmlReader" /> Pointing to the document to deserialize.
/// </param>
/// <returns>
/// <see langword="true" /> If this <see cref="XmlSerializer" /> can deserialize an object, <see cref="XmlReader" /> indicates; otherwise, <see langword="false" />.
/// </returns>
public static bool CanDeserialize(XmlReader xmlReader)
{
return _serializer.CanDeserialize(xmlReader);
}
}
}
It might be too late to party but there is serialization with only user defined Namespaces:
public static string XmlSerialize<T>(this T obj) where T : class
{
Type serialType = typeof(T);
var xsSubmit = new XmlSerializer(serialType);
XmlWriterSettings xws = new XmlWriterSettings() { OmitXmlDeclaration = true, Indent = true };
var Namespaces = new XmlSerializerNamespaces(new XmlQualifiedName[] {
new XmlQualifiedName(string.Empty, GetXmlNameSpace(serialType) ?? string.Empty )
});
private static string GetXmlNameSpace(Type target)
{
XmlRootAttribute attribute = (XmlRootAttribute)Attribute.GetCustomAttribute(target, typeof(XmlRootAttribute));
return attribute == null ? null : attribute.Namespace;
}
And defined namespace in the custom class
[XmlRoot("IdentityTerminal",Namespace = "http://my-name-space/XMLSchema")]
public class IdentityTerminal
{
}
This code allows to user only user defined namespaces and omit default ones.