Deserialize object with struct declared in external library - c#

I have an object I want to deserialize, which is declared as struct in an external library (which is marked as Serializable).However, Json.net is not able to deserialize this object. Serialization is fine, but deserialize doesn't work. I already tried to change struct to class but it didn't help. Do I need to put something special in the JsonSerializerSettings or something else, or isn't it supported? I already tried several of the parameters there, like TypeNameHandling and TypeNameAssemblyFormat, but it didn't work.
As asked, some code, this is declared in external library:
[Serializable]
public struct BarEntry
{
public RegistryValueKind One;
public string Two;
public string Three;
public string Four;
public object Five;
}
[Serializable]
public struct FooEntry
{
public string One;
public string Two;
}
Serialized in own project as:
Stream stream = System.IO.File.Open(fileName, FileMode.Create);
string json = JsonConvert.SerializeObject(entry, Formatting.None, new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects });
StreamWriter streamWriter = new StreamWriter(stream);
streamWriter.Write(json);
streamWriter.Flush();
stream.Close();
Deserialized in own project as:
StreamReader streamReader = new StreamReader(input);
string json = streamReader.ReadToEnd();
object returnObject = JsonConvert.DeserializeObject<T>(json);
input.Close();
return returnObject;
Everything inside own project works fine with this code, but from external library it is not able to deserialize the objects (From both BarEntry and FooEntry).
Also BarEntry and FooEntry are both stored in the same property in their storage object:
public object Entry { get; set; }

You must send exact type to JsonConvert.DeserializeObject, otherwise there is no way to create right object that will have needed properties to deserialize to from json string. So load this type from external assembly and send it to Json.NET. Something like this :
Assembly assembly = Assembly.LoadFile("ExternalAssembly.dll");
Type barEntryType = assembly.GetType("BarEntry");
var returnObject = JsonConvert.DeserializeObject(json, barEntryType);
or reference the external assembly and simply do this :
BarEntry returnObject = JsonConvert.DeserializeObject<BarEntry>(json)

Related

Serialize & Deserialize C# user Defined Classes in .Net

I m working with Core Web API and I have the challenge to nest different class objects into an ArrayList and send them over the FromBody object, the issue is I have to pack them in a way that on the receiving side I deserialize them into their respective objects.
an example is below.
[Serializable]
public class M1
{
public string Name { get; set; }
public int Age { get; set; }
}
[Serializable]
public class M2 : M1
{
public string Gender { get; set; }
public int Height { get; set; }
}
static void Main(string[] args)
{
try
{
M1 mObj = new M1();
M2 m2Obj = new M2();
ArrayList alist = new ArrayList();
mObj.Name = "Apple";
mObj.Age = 20;
m2Obj.Name = "Banana";
m2Obj.Age = 30;
m2Obj.Gender = "Male";
m2Obj.Height = 6;
alist.Add(mObj);
alist.Add(m2Obj);
string result = string.Empty;
M1 mObjD = new M1();
M2 mObj2D = new M2();
//Method1
try
{
result = Newtonsoft.Json.JsonConvert.SerializeObject(alist, Formatting.Indented);
mObjD = Newtonsoft.Json.JsonConvert.DeserializeObject<M1>(result);
mObj2D = Newtonsoft.Json.JsonConvert.DeserializeObject<M2>(result);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
//Method 2
try
{
result = Newtonsoft.Json.JsonConvert.SerializeObject(mObj, Formatting.Indented);
result = result + Newtonsoft.Json.JsonConvert.SerializeObject(m2Obj, Formatting.Indented);
mObjD = Newtonsoft.Json.JsonConvert.DeserializeObject<M1>(result);
mObj2D = Newtonsoft.Json.JsonConvert.DeserializeObject<M2>(result);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
For the first method its throwing error:
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'SerliazeDeserliaze.M1' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array of a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
Path '', line 1, position 1.
for the second method, it says
Additional text encountered after finished reading JSON content: {. Path '', line 4, position 2.
By doing some hack I have done that different way.
M1 mObj = new M1();
M2 m2Obj = new M2();
ArrayList alist = new ArrayList();
ArrayList alistb = new ArrayList();
mObj.Name = "Apple";
mObj.Age = 20;
m2Obj.Name = "Banana";
m2Obj.Age = 30;
m2Obj.Gender = "Male";
m2Obj.Height = 6;
alist.Add(mObj);
alist.Add(m2Obj);
string result = string.Empty;
M1 mObjD = new M1();
M2 mObj2D = new M2();
string json = JsonConvert.SerializeObject(alist, Formatting.Indented, new KeysJsonConverter(typeof(ArrayList)));
alistb= JsonConvert.DeserializeObject<ArrayList>(json, new KeysJsonConverter(typeof(ArrayList)));
mObjD = Newtonsoft.Json.JsonConvert.DeserializeObject<M1>(alistb[0].ToString());
mObj2D = Newtonsoft.Json.JsonConvert.DeserializeObject<M2>(alistb[1].ToString());
Serializing the list into JSON and then Deserializing it in a reverse way get the job done.
If you serialize list of object, you should deserialize it also into list:
string result = Newtonsoft.Json.JsonConvert.SerializeObject(aList, Formatting.Indented);
List<M1> mObjD = Newtonsoft.Json.JsonConvert.DeserializeObject<List<M1>>(result);
JSON supports the following two data structures,
Collection of name/value pairs - This Data Structure is supported by different programming languages.
Ordered list of values - It includes an array, list, vector or sequence, etc.
JSON has the following styles,
Object
An unordered "name/value" assembly. An object begins with "{" and ends with "}". Behind each "name", there is a colon. And comma is used to separate much "name/value". For example,
var user = {"name":"Manas","gender":"Male","birthday":"1987-8-8"}
Array
Value order set. An array begins with "[" and end with "]". And values are separated with commas. For example,
var userlist = [{"user":{"name":"Manas","gender":"Male","birthday":"1987-8-8"}},
{"user":{"name":"Mohapatra","Male":"Female","birthday":"1987-7-7"}}]
String
Any quantity Unicode character assembly which is enclosed with quotation marks. It uses backslash to escape.
var userlist = "{\"ID\":1,\"Name\":\"Manas\",\"Address\":\"India\"}"
We can implement JSON Serialization/Deserialization in the following three ways:
Using JavaScriptSerializer class
Using DataContractJsonSerializer class
Using JSON.NET library
Using DataContractJsonSerializer
DataContractJsonSerializer class helps to serialize and deserialize JSON.
It is present in namespace System.Runtime.Serialization.Json which is
available in assembly System.Runtime.Serialization.dll. Using the
class we can serialize an object into JSON data and deserialize JSON
data into an object.
Let's say there is Employee class with properties such as name, address, and property values also assigned. Now we can convert the Employee class instance to the JSON document. This JSON document can be deserialized into the Employee class or another class with an equivalent data contract. The following code snippets demonstrate about serialization and deserialization.
Let's create a custom class BlogSite for serialization and deserialization,
[DataContract]
class BlogSite
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string Description { get; set; }
}
C# Serialization
In Serialization, it converts a custom .Net object to a JSON string. In the following code, it creates an instance of BlogSiteclass and assigns values to its properties. Then we create an instance of DataContractJsonSerializer class by passing the parameter BlogSite class and create an instance of MemoryStream class to write object(BlogSite). Lastly it creates an instance of StreamReader class to read JSON data from MemorySteam object.
BlogSite bsObj = new BlogSite()
{
Name = "C-sharpcorner",
Description = "Share Knowledge"
};
DataContractJsonSerializer js = new DataContractJsonSerializer(typeof(BlogSite));
MemoryStream msObj = new MemoryStream();
js.WriteObject(msObj, bsObj);
msObj.Position = 0;
StreamReader sr = new StreamReader(msObj);
// "{\"Description\":\"Share Knowledge\",\"Name\":\"C-sharpcorner\"}"
string json = sr.ReadToEnd();
sr.Close();
msObj.Close();
C# Deserialization
In Deserialization, it does the opposite of Serialization, which means it converts JSON string to a custom .Net object. In the following code, it creates an instance of BlogSite class and assigns values to its properties. Then we create an instance of DataContractJsonSerializer class by passing the parameter BlogSite class and creating an instance of MemoryStream class to write an object(BlogSite). Lastly, it creates an instance of StreamReader class to read JSON data from MemorySteam object.
string json = "{\"Description\":\"Share Knowledge\",\"Name\":\"C-sharpcorner\"}";
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
// Deserialization from JSON
DataContractJsonSerializer deserializer = new DataContractJsonSerializer(typeof(BlogSite));
BlogSite bsObj2 = (BlogSite)deserializer.ReadObject(ms);
Response.Write("Name: " + bsObj2.Name); // Name: C-sharpcorner
Response.Write("Description: " + bsObj2.Description); // Description: Share Knowledge
}
C# Using JavaScriptJsonSerializer
JavaScriptSerializer is a class that helps to serialize and deserialize JSON. It is present in the namespace System.Web.Script.Serialization is available in assembly System.Web.Extensions.dll. To serialize a .Net object to JSON string use the Serialize method. It's possible to deserialize JSON string to .Net object using Deserialize or DeserializeObject methods. Let's see how to implement serialization and deserialization using JavaScriptSerializer.
Following code, a snippet is to declare a custom class of BlogSites type.
class BlogSites
{
public string Name { get; set; }
public string Description { get; set; }
}
C# Serialization
In Serialization, it converts a custom .Net object to a JSON string. In the following code, it creates an instance of BlogSiteclass and assigns some values to its properties. Then we create an instance of JavaScriptSerializer and call Serialize() method by passing object(BlogSites). It returns JSON data in string format.
// Creating BlogSites object
BlogSites bsObj = new BlogSites()
{
Name = "C-sharpcorner",
Description = "Share Knowledge"
};
// Serializing object to json data
JavaScriptSerializer js = new JavaScriptSerializer();
string jsonData = js.Serialize(bsObj); // {"Name":"C-sharpcorner","Description":"Share Knowledge"}
C# Deserialization
In Deserialization, it does the opposite of Serialization which means it converts JSON string to custom .Net object. In the following code, it creates a JavaScriptSerializer instance and calls Deserialize() by passing JSON data. It returns a custom object (BlogSites) from JSON data.
// Deserializing json data to object
JavaScriptSerializer js = new JavaScriptSerializer();
BlogSites blogObject = js.Deserialize<BlogSites>(jsonData);
string name = blogObject.Name;
string description = blogObject.Description;
// Other way to whithout help of BlogSites class
dynamic blogObject = js.Deserialize<dynamic>(jsonData);
string name = blogObject["Name"];
string description = blogObject["Description"];
C# Using Json.NET
Json.NET is a third-party library that helps conversion between JSON text and .NET object using the JsonSerializer. The JsonSerializer converts .NET objects into their JSON equivalent text and back again by mapping the .NET object property names to the JSON property names. It is open-source software and free for commercial purposes.
The following are some awesome features,
Flexible JSON serializer for converting between .NET objects and JSON.
LINQ to JSON for manually reading and writing JSON.
High performance, faster than .NET's built-in JSON serializers.
Easy to read JSON.
Convert JSON to and from XML.
Supports .NET 2, .NET 3.5, .NET 4, Silverlight and Windows Phone.
Let’s start learning how to install and implement:
In Visual Studio, go to Tools Menu -> Choose Library Package Manager -> Package Manager Console. It opens a command window where we need to put the following command to install Newtonsoft.Json.
Install-Package Newtonsoft.Json
OR
In Visual Studio, Tools menu -> Manage Nuget Package Manager Solution and type “JSON.NET” to search it online. Here's the figure,
Json.NET
Serialization
In Serialization, it converts a custom .Net object to a JSON string. In the following code, it creates an instance of BlogSiteclass and assigns some values to its properties. Then it calls static method SerializeObject() of JsonConvert class by passing object(BlogSites). It returns JSON data in string format.
// Creating BlogSites object
BlogSites bsObj = new BlogSites()
{
Name = "C-sharpcorner",
Description = "Share Knowledge"
};
// Convert BlogSites object to JOSN string format
string jsonData = JsonConvert.SerializeObject(bsObj);
Response.Write(jsonData);
C# Deserialization
In Deserialization, it does the opposite of Serialization which means it converts JSON string to custom .Net object. In the following code, it calls the static method DeserializeObject() of the JsonConvert class by passing JSON data. It returns a custom object (BlogSites) from JSON data.
string json = #"{
'Name': 'C-sharpcorner',
'Description': 'Share Knowledge'
}";
BlogSites bsObj = JsonConvert.DeserializeObject<BlogSites>(json);
Response.Write(bsObj.Name);
JSON.NET, visit here.
In Visual Studio, Tools menu -> Manage Nuget Package Manger Solution and type “JSON.NET” to search it online. Here's the

How can I deserialize a json object into a complex object?

I'm trying to deserialize a JSON object into an Object with some "object" attribute that may be different each time. I have a serializer/deserializer function that works fine when using simple variable types or defined ones.
I tried to cast the object into the correct class, tried to get the object as dynamic, etc. However, I always get an exception: "Object Reference not established..."
Deserialization func:
public static T deserializeJSON<T>(string json)
{
T obj = Activator.CreateInstance<T>();
using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(json)))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType($
obj = (T)serializer.ReadObject(ms);
}
return obj;
}
Example object:
[DataContract]
class Client
{
[DataMember] private string name;
[DataMember] private string address;
[DataMember] private string bio;
[DataMember] private object specific; //WHERE SPECIFIC MAY BE ANY OTHER OBJECT THAT I CAST AFTER DESERIALIZATION
}
Example object2:
[DataContract]
class Server
{
[DataMember] private string name;
[DataMember] private int value;
}
The specific attribute may be any other object. Imagine "specific" attribute is a Server type object; The deserialization function loads all attributes well instead of specific that is loaded as an object, but cannot convert it to Server.
PD: At deserialization moment, I know what class type is the "specific" attribute.
Thanks!
using latest json.net you can use
dynamic data = Json.Decode(json);
or
dynamic data = JObject.Parse(json);
and can access data with following code :
data.Date;
data.Items.Count;
data.Items[0].Name;
data.Items[0].Price;
data.Items[1].Name;

How to serialize FileInfo object using NewtonSoft Json?

I want to serialize FileInfo object using json.
Till now, I am getting below result upon serializing file info object using JsonConvert.serializeOjbect() method.
FileInfo finfo = new FileInfo("drive:\\folderpath\\file.txt");
string jsonString = JsonConvert.SerializeObject(finfo);
Of course, finfo holds a lot more properties than the two held by jsonString.
(Properties like Exists, Directory, CreationTime, Extension, IsReadonly, LastAccessTime, etc.)
jsonstring only holds two of these properties.
jsonString = {{
"OriginalPath": "drive:\\folderpath\\file.txt",
"FullPath": "drive:\\folderpath\\file.txt"
}}
Is there a way to serialize whole object instead of these two properties using Json?
The reason that you're only seeing those two properties is because FileInfo implements the ISerializable interface, and its GetObjectInfo method is being used to override the default serialization behavior. If you had full control over the FileInfo class (which you don't) then you could apply the [JsonObject] attribute to force normal Json serialization behavior.
I think your only option in this case to write your own wrapper containing the properties that you want. Your properties can just call the underlying FileInfo properties directly.
I'm trying to move forward with #RogerN comment "Your properties can just call the underlying FileInfo properties directly"
I don't see how to be able to serialize/deserialize without using a completely separate data type. Any way I can take in FileInfo for serializing and use the JSON values for deserializing? This is the best I've come up with and "Object reference not set to an instance of an object" error
void Main()
{
var res = Directory.GetFiles(#"C:\Users\kelly\OneDrive\Code\LinqPAD6 Portable\")
.Take(3)
.Select(d => new MyFileInfo2(new FileInfo(d)));
var jsonPath = #"C:\Users\Public\Documents\tst.json";
var json = System.Text.Json.JsonSerializer.Serialize(res, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(jsonPath, json);
Thread.Sleep(100);
json = File.ReadAllText(jsonPath);
var readFromJson = System.Text.Json.JsonSerializer.Deserialize<List<MyFileInfo2>>(json);
readFromJson.Dump();
}
public class MyFileInfo2
{
private readonly FileInfo _fi;
public MyFileInfo2(FileInfo fi)
{
_fi = fi;
Path = fi.FullName;
Size = fi.Length;
}
public MyFileInfo2()
{
}
public string Path
{
get
{
return _fi.FullName;
}
set
{
value = Path;
}
}
public long Size { get; set; }
}

How to serialize multiple members of "this"

I have a class with a couple of members I want to serialise to store state.
However, I want to serialise from WITHIN the class itself, not via some external class feeding it to a formatter.
So in theory I want to do something like:
[DataContract]
class MyClass
{
[DataMember]
private MyCompoundClass _someCompoundField;
[DataMember]
private int _someOtherField;
private void SaveState()
{
using (Stream stream = GetStream())
{
DataContractSerializer serialiser = new DataContractSerializer(typeof(MyClass));
serialiser.WriteObject(stream, this);
}
}
private void LoadState()
{
using (Stream stream = GetStream())
{
DataContractSerializer serialiser = new DataContractSerializer(typeof(MyClass));
this = (MyClass)serialiser.ReadObject(stream);
}
}
}
Now obviously the line
this = (MyClass)serialiser.ReadObject(stream);
is nonsense, but you can see what I'm trying to do. I want to serialise the two fields of my class from within the class. (I am using the WCF serializer, but I assume this will be the same if I use XmlSerializer).
I tried to implement this properly by serialising each field myself like so:
private void SaveState()
{
using (Stream stream = GetStream())
{
//serialise field 1
DataContractSerializer serialiser = new DataContractSerializer(typeof(MyCompoundClass));
serialiser.WriteObject(stream, _someCompoundField);
//serialise field 2
serialiser = new DataContractSerializer(typeof(int));
serialiser.WriteObject(stream, _someOtherField);
}
}
Now this works as a save, but when I come to read the document back in it throws an exception since there are two root nodes in the XML file.
How do I create my "wrapper" node to wrap my fields. Or is there some other way I should be doing this?
Many thanks,
I haven't seen any built-in deserialisation methods which modify an existing object, rather than returning a new one. Your options as I see them are:
Deserialise a new MyClass and copy the members over
Make LoadState static and have it return the deserialised MyClass
Use a different serialisation mechanism which can do what you want
you could at your LoadState do:
private void LoadState()
{
using (Stream stream = GetStream())
{
DataContractSerializer serialiser = new DataContractSerializer(typeof(MyClass));
MyClass deserialized = (MyClass)serialiser.ReadObject(stream);
this._someCompoundField = deserialized._someCompoundField;
this._someOtherField = deserialized._someOtherField;
}
}
Are you tied to a specific serializer? protobuf-net supports that use-case, for example:
[DataContract]
class MyClass
{
[DataMember(Order = 1)]
private MyCompoundClass _someCompoundField;
[DataMember(Order = 2)]
private int _someOtherField;
private void SaveState()
{
using (Stream stream = GetStream())
{
ProtoBuf.Serializer.Serialize(stream, this);
}
}
private void LoadState()
{
using (Stream stream = GetStream())
{
ProtoBuf.Serializer.Merge(stream, this);
}
}
}
Note the addition of Order = n on the member-attributes; that is because protobuf uses numeric identifiers on fields/properties, and needs a way to choose them. You can also use the project-specific [ProtoContract]/[ProtoMember(n)] attributes, but it works with the WCF ones too (as shown).
(Merge is also available on the non-generic 2.0 API - but you pass this in as an argument to Deseroalize instead)
Put your deserialization method in a static method:
class MyClass
{
public static MyClass LoadState()
{
// Deserialize, and return the new MyClass instance.
}
}
To serialize just some objects, annotate some fields to avoid serialization, or create a superclass or interface with just the fields in it you want to serialize.

How to serialize/deserialize a C# class?

I have an object in Javascript that looks like this
function MyObject(){
this.name="";
this.id=0;
this.....
}
I then stringify an array of those objects and send it to an ASP.Net web service.
At the webservice I want to unserialize the JSON string so I can deal with the data easily in C#. Then, I want to send an array of objects of the same Javascript type(same field names and everything) back to the client. The thing I'm not understanding is how to serialize say this class:
class MyObject{
public string Name;
public int ID;
}
so that the JSON is the same as the above javascript object. And also how to unserialize into the C# MyObject class.
How would I do this easily? I am using Netwonsoft.Json.
Is there some way to turn a JSON string into a List or Array of an object?
with json.net you can use the JsonPropertyAttribute to give your serialized properties a custom name:
class MyObject{
[JsonProperty(PropertyName = "name")]
public string Name;
[JsonProperty(PropertyName = "id")]
public int ID;
}
you can then serialize your object into a List<> like so:
var list = new List<MyObject>();
var o = new MyObject();
list.Add(o);
var json = JsonConvert.SerializeObject(list);
and deserialize:
// json would look like this "[{ "name":"", "id":0 }]"
var list = JsonConvert.DeserializeObject<List<MyObject>>(json);
One thing the WebMethod gives you back is a "d" wrapper which I battled with for hours to get around. My solution with the Newtonsoft/JSON.NET library is below. There might be an easier way to do this I'd be interested to know.
public class JsonContainer
{
public object d { get; set; }
}
public T Deserialize<T>(string json)
{
JsonSerializer serializer = new JsonSerializer();
JsonContainer container = (JsonContainer)serializer.Deserialize(new StringReader(json), typeof(JsonContainer));
json = container.d.ToString();
return (T)serializer.Deserialize(new StringReader(json), typeof(T));
}
You can try the DataContractJsonSerializer Rick Strahl Has a fairly good example.
You tell the serializer the type that you are serializing to and you can decorate the class properties telling them to expect a different name.
As an example:
class MyObject{
[DataMember(name="name")]
public string Name;
[DataMember(name="id")]
public int ID;
}
EDIT: Use
using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonString)))
{
ser = new DataContractJsonSerializer(typeof(MyObject));
MyObject obj = ser.ReadObject(ms) as MyObject;
int myObjID = obj.ID;
string myObjName = obj.Name;
}

Categories