I have a bunch of xml files that I need to deserialize and store in a database.
I found a generic implementation of an XML deserilizer that does a great job. The only inconvenient is that I cannot deserialize the Celsius degree sign.
The following XML samples contain the Celsius degree sign, which I cannot deserialize:
<pt>
<ch>1</ch>
<type>Analog</type>
<chtype>Temperature</chtype>
<chunits>°C</chunits>
<time>2020-05-03 22:10:00</time>
<value>0</value>
</pt>
or
<pt>
<ch>5</ch>
<type>Analog</type>
<chtype>Wind Direction</chtype>
<chunits>°</chunits>
<time>2020-05-03 22:10:00</time>
<value>0</value>
</pt>
My Deserializer implementation is the following:
public class XmlConvert
{
public static string SerializeObject<T>(T dataObject)
{
if (dataObject == null)
{
return string.Empty;
}
try
{
using (StringWriter stringWriter = new System.IO.StringWriter())
{
var serializer = new XmlSerializer(typeof(T));
serializer.Serialize(stringWriter, dataObject);
return stringWriter.ToString();
}
}
catch (Exception ex)
{
return string.Empty;
}
}
public static T DeserializeObject<T>(string xml)
where T : new()
{
if (string.IsNullOrEmpty(xml))
{
return new T();
}
try
{
using (var stringReader = new StringReader(xml))
{
var serializer = new XmlSerializer(typeof(T));
return (T)serializer.Deserialize(stringReader);
}
}
catch (Exception ex)
{
return new T();
}
}
}
The class I use to convert is the following:
/// <summary>
/// Container for a single data point.
/// </summary>
public class MessageDataPoint
{
/// <summary>
/// Channel number for data point.
/// </summary>
[System.Xml.Serialization.XmlElement("ch")]
public string Ch { get; set; }
/// <summary>
/// Point type (Analog, Flow)
/// </summary>
[System.Xml.Serialization.XmlElement("type")]
public string Type { get; set; }
/// <summary>
///
/// </summary>
[System.Xml.Serialization.XmlElement("chtype")]
public string ChType { get; set; }
/// <summary>
/// Channel units
/// </summary>
[System.Xml.Serialization.XmlElement("chunits")]
public string ChUnits { get; set; }
/// <summary>
/// Point timestamp.
/// </summary>
[System.Xml.Serialization.XmlElement("time")]
public string Time { get; set; }
[System.Xml.Serialization.XmlIgnore]
public DateTime? TimeParsed
{
get
{
DateTime.TryParse(Time, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dt);
return dt;
}
private set { }
}
/// <summary>
/// Channel Value
/// </summary>
[System.Xml.Serialization.XmlElement("value")]
public string Value { get; set; }
}
The deserializer implementation is the following:
public async Task<string> GetFileAsStream(string key)
{
var content = string.Empty;
try
{
GetObjectRequest request = new GetObjectRequest
{
BucketName = bucketName,
Key = key
};
using (GetObjectResponse response = await client.GetObjectAsync(request))
{
using (StreamReader reader = new StreamReader(response.ResponseStream))
{
content = await reader.ReadToEndAsync();
var logger = XmlConvert.DeserializeObject<Logger>(content);
// code removed for brevity
}
}
}
}
The result is the following:
<pt>
<ch>1</ch>
<type>Analog</type>
<chtype>Temperature</chtype>
<chunits>�C</chunits>
<time>2020-05-03 22:10:00</time>
<value>0</value>
</pt>
<pt>
<ch>2</ch>
<type>Analog</type>
<chtype>Wind Chill</chtype>
<chunits>�C</chunits>
<time>2020-05-03 22:10:00</time>
<value>0</value>
</pt>
Any ideas?
This is a sample file:
<?xml version="1.0" encoding="ISO-8859-15"?>
<logger>
<id>111111</id>
<mobileNumber>12345676</mobileNumber>
<serialNumber>01404</serialNumber>
<siteName>abcdef</siteName>
<siteId>abcdef</siteId>
<maintenanceflag>False</maintenanceflag>
<messages>
<message>
<id>123456789</id>
<number>123456</number>
<dateReceived>2020-05-04 00:02:25.0</dateReceived>
<dateCredited>2020-05-04 00:02:25.0</dateCredited>
<message> <siteId>abcdef</siteId>
<type>data</type>
<RST>2020-01-18 08:50:00</RST>
<RTC>2020-05-03 23:02:24</RTC>
<DST>2020-05-03 22:00:00</DST>
<mode>0</mode>
<SR>600</SR>
<pt>
<ch>1</ch>
<type>Analog</type>
<chtype>Temperature</chtype>
<chunits>°C</chunits>
<time>2020-05-03 23:00:00</time>
<value>0</value>
</pt>
<pt>
<ch>5</ch>
<type>Analog</type>
<chtype>Wind Direction</chtype>
<chunits>°</chunits>
<time>2020-05-03 23:00:00</time>
<value>0</value>
</pt>
</message>
<format>BINARY</format>
<source>FTP</source>
<batteryCondition>123</batteryCondition>
<signalStrength>12</signalStrength>
</message>
</messages>
</logger>
Feed the stream to the serializer. This will greatly simplify the code.
Moreover, you can completely delete your XmlConvert class.
using (GetObjectResponse response = await client.GetObjectAsync(request))
using (var stream = response.ResponseStream)
{
var serializer = new XmlSerializer(typeof(Logger));
var logger = (Logger)serializer.DeserializeObject(stream);
}
But if you think that the XmlConvert class is necessary, for example, it does some extra work, then at least use Stream in it instead of string.
public static T DeserializeObject<T>(Stream stream)
where T : new()
{
try
{
var serializer = new XmlSerializer(typeof(T));
return (T)serializer.Deserialize(stream);
}
catch (Exception ex)
{
return new T();
}
}
I found the solution by looking at the following post on Stackoverflow
Using .NET how to convert ISO 8859-1 encoded text files that contain Latin-1 accented characters to UTF-8
Thanks to Nyerguds and Alexander Haas for pointing me in the right direction
The solution for me was
public async Task<string> GetFileAsStream(string key)
{
var content = string.Empty;
try
{
GetObjectRequest request = new GetObjectRequest
{
BucketName = bucketName,
Key = key
};
using (GetObjectResponse response = await client.GetObjectAsync(request))
{
using (StreamReader reader = new StreamReader(response.ResponseStream, Encoding.GetEncoding("iso-8859-1")))
{
content = await reader.ReadToEndAsync();
var logger = XmlConvert.DeserializeObject<Logger>(content);
// code removed for brevity
}
}
}
}
Related
I ran into an issue recently when in an existing Console Application project we're forced to remove a reference to WSE 3.0. When I tried to remove it from references (because I could not find where it's used) it turned out there is only one place and it's using the SoapEnvelope class.
A little bit about the application: it's a console application that connects to an Exchange Server and listens to incoming emails, around 2-3k emails daily.
The SoapEnvelope class is used to read and parse the email body:
/// <summary>
/// Reads content of received HTTP request.
/// </summary>
/// <param name="client">The specified client.</param>
/// <returns>The watermark string if the read is successful; otherwise the last watermark.</returns>
public string Read(TcpClient client)
{
try
{
_myReadBuffer = new byte[client.ReceiveBufferSize];
using (var networkStream = client.GetStream())
{
var httpRequest = new MailboxHttpRequest(networkStream);
if (httpRequest.HasBody)
{
var httpResponse = new MailboxHttpResponse(_mailbox);
httpResponse.ParseBody(httpRequest.Body);
httpResponse.Send(networkStream, httpRequest.Body);
}
return httpRequest.Watermark;
}
}
catch (Exception ex)
{
Logger.WriteErrorLine("[EventsCollector] Error calling Read in MailboxNotificationManager", ex);
return _mailbox.LastWatermark;
}
finally
{
_myReadBuffer = null;
}
}
And the ParseBody methods looks like this:
/// <summary>
/// Parses the XML body content of receive notification and initialized email processing, if new message was received.
/// </summary>
/// <param name="body">XML content of received notification.</param>
public void ParseBody(string body)
{
var soapEnvelope = new SoapEnvelope() { InnerXml = body };
var serializer = new XmlSerializer(typeof(SendNotificationResponseType));
using (var reader = new XmlNodeReader(soapEnvelope.Body.FirstChild))
{
var notificationResponse = (SendNotificationResponseType)serializer.Deserialize(reader);
if (notificationResponse.ResponseMessages != null) // Process notification, if request contains response message
{
_result = processNotification(notificationResponse);
}
}
}
As you can see, it creates a SoapEnvelope class to access the body`s first child.
MailboxHttpRequest class
private class MailboxHttpRequest
{
private readonly Regex _httpRequestBodyLengthPattern = new Regex(#"Content-Length: (?<BodyLength>\d*)", RegexOptions.Compiled);
private readonly Regex _httpRequestBodyPattern = new Regex(#"<\?xml .*", RegexOptions.Compiled);
private readonly Regex _httpRequestWatermarkPattern = new Regex(#"<t:Watermark>(?<Watermark>.*?)<\/t:Watermark>", RegexOptions.Compiled);
private const int _bufferSize = 8192;
public bool HasBody
{
get { return !String.IsNullOrEmpty(Body); }
}
public string Body { get; private set; }
public string Watermark { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="MailboxHttpRequest"/> class and reads incoming messages
/// </summary>
/// <param name="networkStream">The network stream.</param>
public MailboxHttpRequest(NetworkStream networkStream)
{
var completeRequest = new StringBuilder();
var readBuffer = new byte[_bufferSize];
do // Read incoming message that might consist of many parts
{
var newDataLength = networkStream.Read(readBuffer, 0, readBuffer.Length);
completeRequest.Append(Encoding.ASCII.GetString(readBuffer, 0, newDataLength));
}
while (networkStream.DataAvailable || !requestWasFullyReceived(completeRequest.ToString()));
Body = _httpRequestBodyPattern.Match(completeRequest.ToString())
.Value;
Watermark = _httpRequestWatermarkPattern.Match(Body).Groups["Watermark"].Value;
}
}
The downside is that I`m not able test this part of code since I cant listen to same mailbox so I cant check what and how does the passed string look like.
If anybody has any suggestion on how to replace the SoapEnvelope class, would be greatly appreciate it.
Cosmin
As i read readme.txt for latest RestSharp:
*** IMPORTANT CHANGE IN RESTSHARP VERSION 103 ***
In 103.0, JSON.NET was removed as a dependency.
If this is still installed in your project and no other libraries depend on
it you may remove it from your installed packages.
There is one breaking change: the default Json*Serializer* is no longer
compatible with Json.NET. To use Json.NET for serialization, copy the code
from https://github.com/restsharp/RestSharp/blob/86b31f9adf049d7fb821de8279154f41a17b36f7/RestSharp/Serializers/JsonSerializer.cs
and register it with your client:
var client = new RestClient();
client.JsonSerializer = new YourCustomSerializer();
The default Json*Deserializer* is mostly compatible, but it does not support
all features which Json.NET has (like the ability to support a custom [JsonConverter]
by decorating a certain property with an attribute). If you need these features, you
must take care of the deserialization yourself to get it working.
Im already installed Newtonsoft.Json with nu package manager, and im trying to register Json.NET to client variable, but didn't work. here is my code:
private void Form1_Load(object sender, EventArgs e)
{
var client = new RestClient("http://homestead.app/vendor");
client.JsonSerializer = new JsonSerializer(); <-- HERE IS THE ERROR
var request = new RestRequest("", Method.GET);
IRestResponse response = client.Execute(request);
var content = response.Content; // raw content as string
textBox1.Text = content;
}
the client.JsonSerializer property is not available.
Please kindly help me. thanks
The serializers for RestSharp must implement two interfaces:
RestSharp.Serializers.ISerializer
RestSharp.Serializers.IDeserializer
You must wrap the serializer from Newtonsoft to type with these interfaces.
There is working code from one project I worked on:
/// <summary>
/// Default JSON serializer for request bodies
/// Doesn't currently use the SerializeAs attribute, defers to Newtonsoft's attributes
/// </summary>
/// <remarks>
/// Based on http://blog.patrickmriley.net/2014/02/restsharp-using-jsonnet-serializer.html
/// </remarks>
public class RestSharpJsonNetSerializer : RestSharp.Serializers.ISerializer, RestSharp.Deserializers.IDeserializer
{
private readonly JsonSerializer serializer;
/// <summary>
/// Default serializer
/// </summary>
public RestSharpJsonNetSerializer()
{
this.ContentType = "application/json";
this.serializer = new JsonSerializer
{
MissingMemberHandling = MissingMemberHandling.Ignore,
NullValueHandling = NullValueHandling.Include,
DefaultValueHandling = DefaultValueHandling.Include
};
}
/// <summary>
/// Default serializer with overload for allowing custom Json.NET settings
/// </summary>
public RestSharpJsonNetSerializer(JsonSerializer serializer)
{
this.ContentType = "application/json";
this.serializer = serializer;
}
/// <summary>
/// Unused for JSON Serialization
/// </summary>
public string DateFormat { get; set; }
/// <summary>
/// Unused for JSON Serialization
/// </summary>
public string RootElement { get; set; }
/// <summary>
/// Unused for JSON Serialization
/// </summary>
public string Namespace { get; set; }
/// <summary>
/// Content type for serialized content
/// </summary>
public string ContentType { get; set; }
/// <summary>
/// Serialize the object as JSON
/// </summary>
/// <param name="obj">Object to serialize></param>
/// <returns>JSON as String</returns>
public string Serialize(object obj)
{
using (var stringWriter = new StringWriter())
{
using (var jsonTextWriter = new JsonTextWriter(stringWriter))
{
jsonTextWriter.Formatting = Formatting.Indented;
jsonTextWriter.QuoteChar = '"';
this.serializer.Serialize(jsonTextWriter, obj);
var result = stringWriter.ToString();
return result;
}
}
}
public T Deserialize<T>(RestSharp.IRestResponse response)
{
using (var strReader = new StringReader(response.Content))
{
using (var jsonReader = new JsonTextReader(strReader))
{
var data = this.serializer.Deserialize<T>(jsonReader);
return data;
}
}
}
}
The new readme.txt is updated at least in GitHub but the package still contains the old code.
So the answer of #TcKs is correct:
var request = new RestRequest();
request.JsonSerializer = new Shared.JsonSerializer();
var client = new RestClient();
client.Post(request);
It will be easy if you using mapper object when return
public YourResultBase Login(string username, string password)
{
var client = new RestClient("apiUrl");
var request = new RestRequest(Method.GET)
{
OnBeforeDeserialization = resp => { resp.ContentType = "application/json"; }
};
request.AddHeader("Cache-Control", "no-cache");
IRestResponse<YourResultBase> response = client.Execute<YourResultBase>(request);
var result = response.Data;
return result;
}
So I am trying to deserialize and serialize a List.
The issue: The list(list1) is not saving to the file called "ListData" which should be created if not already there, into the documents folder in the android internal storage.
I think the file may not be creating properly or something, or the filepath is incorrect. Below is how it should be functioning but that isn't working as explained with the issue above.
I want to save the filename as something like "ListData".
Also, needs to be saved into the Internal Storage somewhere such as the Data folder of the app or Documents in internal storage.
The following is what i have for the code, but I can't seem to find any help elsewhere to fix my issue. It doesn't work, any ideas for a solution to what I want it to do?
Code:
public abstract class DataHandler
{
public static void SaveLists()
{
string filePath = Android.OS.Environment.DirectoryDocuments;
string fileName = "ListData";
XmlSerializer serializer = new XmlSerializer(typeof(List<Item>));
Stream writer = new FileStream(filePath, FileMode.Create);
serializer.Serialize(writer, _LISTFROMANOTHERCLASS_);
writer.Close();
}
public static void LoadLists()
{
string filePath = Android.OS.Environment.DirectoryDocuments;
string fileName = "ListData";
XmlSerializer serializer = new XmlSerializer(typeof(List<Item>));
Stream reader = new FileStream(filePath, FileMode.Open);
List<Item> list1 = new List<Item>();
list1 = (List<Item>) serializer.Deserialize(reader);
_LISTFROMANOTHERCLASS_ = list1;
reader.Close();
}
}
Hi I have written a class to do these but with JSON serlization check is it helps it uses MVVM Cross, It has code written to encrypt and decrypt data you can avoid these parts
public class PersistantStorageHelper<T>
{
IMvxFileStoreAsync _mvxFileStoreAsync;
IMvxFileStore _mvxFileStore;
EDEngine bcEngine = new EDEngine(new AesEngine(), Encoding.UTF8);
string currentkey_temp_dev = "AthulHarikumar00";//This static key is not being used it is a just a place holder
public PersistantStorageHelper() {
this._mvxFileStore = Mvx.Resolve<IMvxFileStore>();
this._mvxFileStoreAsync = Mvx.Resolve<IMvxFileStoreAsync>();
bcEngine.SetPadding(new Pkcs7Padding());
currentkey_temp_dev = Constants.PassPhrase.Substring(4, 12)+"Road";
}
/// <summary>
///
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public async Task<T> GetPersistantObject(T obj)
{
var fileName = (typeof(T).ToString().Replace(".", "_"));
var x= await GetPersistantObject(obj, fileName);
return x;
}
/// <summary>
/// If object exists returns the object else saves a plain object and returns it
/// </summary>
/// <param name="obj">empty placeholder object</param>
/// <returns>Filesystem object</returns>
public async Task<T> GetPersistantObject( T obj,string fileName) {
List<string> files = new List<string>(_mvxFileStore.GetFilesIn(_mvxFileStore.NativePath("")));
fileName = _mvxFileStore.NativePath(fileName);
if (!files.Contains(fileName))
{
var objJson = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
objJson= bcEngine.Encrypt(objJson, currentkey_temp_dev);
await _mvxFileStoreAsync.WriteFileAsync(fileName,objJson);
}
else {
try
{
var temp = await _mvxFileStoreAsync.TryReadTextFileAsync(fileName);
var str = bcEngine.Decrypt(temp.Result, currentkey_temp_dev);
obj = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(str);
}
catch(Exception e) {
var objJson = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
objJson = bcEngine.Encrypt(objJson, currentkey_temp_dev);
await _mvxFileStoreAsync.WriteFileAsync(fileName, objJson);
}
}
return obj;
}
/// <summary>
///
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public async Task<T> SetPersistantObject(T obj)
{
var fileName = _mvxFileStore.NativePath(typeof(T).ToString().Replace(".", "_"));
var temp = await SetPersistantObject(obj, fileName);
return temp;
}
/// <summary>
/// Saves object to persistant storage with encryption
/// </summary>
/// <param name="obj">object to be stored</param>
/// <returns>Saved object</returns>
public async Task<T> SetPersistantObject(T obj,string fileName)
{
List<string> files = new List<string>(_mvxFileStore.GetFilesIn(_mvxFileStore.NativePath("")));
fileName = _mvxFileStore.NativePath(fileName);
var objJson = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
objJson = bcEngine.Encrypt(objJson, currentkey_temp_dev);
await _mvxFileStoreAsync.WriteFileAsync(fileName, objJson);
return obj;
}
}
java.util.List is not serializable, but java.util.ArrayList is. So just change List to ArrayList on both sites (left before variablename and right for constructor). Also check if your Item implements Serializable
I am receiving the following error trying to deserialize xml. This produces the error:
XmlSerializer serializer = new XmlSerializer(typeof(PrivateOptionsAPIResponse));
var result = serializer.Deserialize(streamReader);
Exception:
System.InvalidOperationException was caught
Message=There is an error in XML document (0, 0)
InnerException: System.Xml.XmlException
Message=Root element is missing
Source=System.Xml
I am not sure how to correct the problem. Request returns the following XML:
<PrivateOptionsAPIResponse>
<CountiesForPostalCodeResponse>
<Counties>
<County>
<CountyName>PRINCE WILLIAM</CountyName>
<StateCode>VA</StateCode>
</County>
<County>
<CountyName>MANASSAS CITY</CountyName>
<StateCode>VA</StateCode>
</County>
<County>
<CountyName>MANASSAS PARK CITY</CountyName>
<StateCode>VA</StateCode>
</County>
</Counties>
</CountiesForPostalCodeResponse>
</PrivateOptionsAPIResponse>
I used xsd.exe to generate a class. The definition on PrivateOptionsAPIResponse (generated by xsd.exe tool) shows:
public partial class PrivateOptionsAPIResponse {
private object itemField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("CountiesForPostalCodeResponse", typeof(ZipCodeValidationResponse))]
[System.Xml.Serialization.XmlElementAttribute("PlanDetailsForIndividualOrFamilyResponse", typeof(IndividualPlanBenefitResponse))]
[System.Xml.Serialization.XmlElementAttribute("PlansForIndividualOrFamilyResponse", typeof(IndividualPlanQuoteResponse))]
[System.Xml.Serialization.XmlElementAttribute("ProductDetailsForSmallGroupResponse", typeof(SmallGroupProductBenefitResponse))]
[System.Xml.Serialization.XmlElementAttribute("ProductsForSmallGroupResponse", typeof(SmallGroupProductQuoteResponse))]
public object Item {
get {
return this.itemField;
}
set {
this.itemField = value;
}
}
}
If I then browse to ZipCodeValidationResponse definition it shows this:
public partial class ZipCodeValidationResponse {
private CountyType[] countiesField;
/// <remarks/>
[System.Xml.Serialization.XmlArrayItemAttribute("County", IsNullable=false)]
public CountyType[] Counties {
get {
return this.countiesField;
}
set {
this.countiesField = value;
}
}
}
If I then browse definition on CountyType I see this:
public partial class CountyType {
private string countyNameField;
private StateAbbreviationType stateCodeField;
/// <remarks/>
public string CountyName {
get {
return this.countyNameField;
}
set {
this.countyNameField = value;
}
}
/// <remarks/>
public StateAbbreviationType StateCode {
get {
return this.stateCodeField;
}
set {
this.stateCodeField = value;
}
}
}
----------Working solution----------------:
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
string status = ((HttpWebResponse)response).StatusDescription;
if(status == "OK")
{
using (Stream responseStream = response.GetResponseStream())
{
using (StreamReader reader = new StreamReader(responseStream))
{
var xmlSerializer = new XmlSerializer(typeof(PrivateOptionsAPIResponse));
var privateOptionsAPIResponse = xmlSerializer.Deserialize(reader) as PrivateOptionsAPIResponse;
}
}
}
}
How are you declaring your streamReader? Take a look at its contents and you'll most likely see it's empty or doesn't contain a complete XML document.
First, check whether your XML is in valid form. From the given exception, it seems you are supplying an invalid xml document. Much appreciate if you could post the content (xml) that you are trying to de serialize.
I'm trying to build a Metro application for Windows 8 on Visual Studio 2011.
and while I'm trying to do that, I'm having some issues on how to parse JSON without JSON.NET library (It doesn't support the metro applications yet).
Anyway, I want to parse this:
{
"name":"Prince Charming",
"artist":"Metallica",
"genre":"Rock and Metal",
"album":"Reload",
"album_image":"http:\/\/up203.siz.co.il\/up2\/u2zzzw4mjayz.png",
"link":"http:\/\/f2h.co.il\/7779182246886"
}
You can use the classes found in the System.Json Namespace which were added in .NET 4.5. You need to add a reference to the System.Runtime.Serialization assembly
The JsonValue.Parse() Method parses JSON text and returns a JsonValue:
JsonValue value = JsonValue.Parse(#"{ ""name"":""Prince Charming"", ...");
If you pass a string with a JSON object, you should be able to cast the value to a JsonObject:
using System.Json;
JsonObject result = value as JsonObject;
Console.WriteLine("Name .... {0}", (string)result["name"]);
Console.WriteLine("Artist .. {0}", (string)result["artist"]);
Console.WriteLine("Genre ... {0}", (string)result["genre"]);
Console.WriteLine("Album ... {0}", (string)result["album"]);
The classes are quite similar to those found in the System.Xml.Linq Namespace.
I use this...but have never done any metro app development, so I don't know of any restrictions on libraries available to you. (note, you'll need to mark your classes as with DataContract and DataMember attributes)
public static class JSONSerializer<TType> where TType : class
{
/// <summary>
/// Serializes an object to JSON
/// </summary>
public static string Serialize(TType instance)
{
var serializer = new DataContractJsonSerializer(typeof(TType));
using (var stream = new MemoryStream())
{
serializer.WriteObject(stream, instance);
return Encoding.Default.GetString(stream.ToArray());
}
}
/// <summary>
/// DeSerializes an object from JSON
/// </summary>
public static TType DeSerialize(string json)
{
using (var stream = new MemoryStream(Encoding.Default.GetBytes(json)))
{
var serializer = new DataContractJsonSerializer(typeof(TType));
return serializer.ReadObject(stream) as TType;
}
}
}
So, if you had a class like this...
[DataContract]
public class MusicInfo
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string Artist { get; set; }
[DataMember]
public string Genre { get; set; }
[DataMember]
public string Album { get; set; }
[DataMember]
public string AlbumImage { get; set; }
[DataMember]
public string Link { get; set; }
}
Then you would use it like this...
var musicInfo = new MusicInfo
{
Name = "Prince Charming",
Artist = "Metallica",
Genre = "Rock and Metal",
Album = "Reload",
AlbumImage = "http://up203.siz.co.il/up2/u2zzzw4mjayz.png",
Link = "http://f2h.co.il/7779182246886"
};
// This will produce a JSON String
var serialized = JSONSerializer<MusicInfo>.Serialize(musicInfo);
// This will produce a copy of the instance you created earlier
var deserialized = JSONSerializer<MusicInfo>.DeSerialize(serialized);
For those who do not have 4.5, Here is my library function that reads json. It requires a project reference to System.Web.Extensions.
using System.Web.Script.Serialization;
public object DeserializeJson<T>(string Json)
{
JavaScriptSerializer JavaScriptSerializer = new JavaScriptSerializer();
return JavaScriptSerializer.Deserialize<T>(Json);
}
Usually, json is written out based on a contract. That contract can and usually will be codified in a class (T). Sometimes you can take a word from the json and search the object browser to find that type.
Example usage:
Given the json
{"logEntries":[],"value":"My Code","text":"My Text","enabled":true,"checkedIndices":[],"checkedItemsTextOverflows":false}
You could parse it into a RadComboBoxClientState object like this:
string ClientStateJson = Page.Request.Form("ReportGrid1_cboReportType_ClientState");
RadComboBoxClientState RadComboBoxClientState = DeserializeJson<RadComboBoxClientState>(ClientStateJson);
return RadComboBoxClientState.Value;
I needed a JSON serializer and deserializer without any 3rd party dependency or nuget, that can support old systems, so you don't have to choose between Newtonsoft.Json, System.Text.Json, DataContractSerializer, JavaScriptSerializer, etc. depending on the target platform.
So I have started this open source (MIT) project here:
https://github.com/smourier/ZeroDepJson
It's just one C# file ZeroDepJson.cs, compatible with .NET Framework 4.x to .NET Core, and .NET 5.
Note it's probably not as good as all the aforementioned libraries (especially in performance area), but it should be reasonably ok and friction-free.
Have you tried using JavaScriptSerializer ?
There's also DataContractJsonSerializer
I have written a small construct to do that long back, it requires System.Runtime.Serialization.Json namespace. It uses DataContractJsonSerializer to serialize & deserialize object with a static method JConvert.
It works with small set of data but haven't tested with big data source.
JsonHelper.cs
// Json Serializer without NewtonSoft
public static class JsonHelper
{
public static R JConvert<P,R>(this P t)
{
if(typeof(P) == typeof(string))
{
var return1 = (R)(JsonDeserializer<R>(t as string));
return return1;
}
else
{
var return2 = (JsonSerializer<P>(t));
R result = (R)Convert.ChangeType(return2, typeof(R));
return result;
}
}
private static String JsonSerializer<T>(T t)
{
var stream1 = new MemoryStream();
var ser = new DataContractJsonSerializer(typeof(T));
ser.WriteObject(stream1, t);
stream1.Position = 0;
var sr = new StreamReader(stream1);
return (sr.ReadToEnd());
}
private static T JsonDeserializer<T>(string jsonString)
{
T deserializedUser = default(T);
var ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));
var ser = new DataContractJsonSerializer(typeof(T));
deserializedUser = (T)ser.ReadObject(ms);// as T;
ms.Close();
return deserializedUser;
}
}
Syntax:
To use the JsonHelper you need to call
JConvert<string,object>(str); //to Parse string to non anonymous <object>
JConvert<object,string>(obj); //to convert <obj> to string
Example:
Suppose we have a class person
public class person
{
public string FirstName {get;set;}
public string LastName {get;set;}
}
var obj = new person();//"vinod","srivastav");
obj.FirstName = "vinod";
obj.LastName = "srivastav";
To convert the person object we can call:
var asText = JsonHelper.JConvert<person,string>(obj); //to convert <obj> to string
var asObject = JsonHelper.JConvert<string,person>(asText); //to convert string to non-anonymous object
You can use DataContractJsonSerializer. See this link for more details.
using System;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;
namespace OTL
{
/// <summary>
/// Before usage: Define your class, sample:
/// [DataContract]
///public class MusicInfo
///{
/// [DataMember(Name="music_name")]
/// public string Name { get; set; }
/// [DataMember]
/// public string Artist{get; set;}
///}
/// </summary>
/// <typeparam name="T"></typeparam>
public class OTLJSON<T> where T : class
{
/// <summary>
/// Serializes an object to JSON
/// Usage: string serialized = OTLJSON<MusicInfo>.Serialize(musicInfo);
/// </summary>
/// <param name="instance"></param>
/// <returns></returns>
public static string Serialize(T instance)
{
var serializer = new DataContractJsonSerializer(typeof(T));
using (var stream = new MemoryStream())
{
serializer.WriteObject(stream, instance);
return Encoding.Default.GetString(stream.ToArray());
}
}
/// <summary>
/// DeSerializes an object from JSON
/// Usage: MusicInfo deserialized = OTLJSON<MusicInfo>.Deserialize(json);
/// </summary>
/// <param name="json"></param>
/// <returns></returns>
public static T Deserialize(string json)
{
if (string.IsNullOrEmpty(json))
throw new Exception("Json can't empty");
else
try
{
using (var stream = new MemoryStream(Encoding.Default.GetBytes(json)))
{
var serializer = new DataContractJsonSerializer(typeof(T));
return serializer.ReadObject(stream) as T;
}
}
catch (Exception e)
{
throw new Exception("Json can't convert to Object because it isn't correct format.");
}
}
}
}