How to serialize/deserialize a C# class? - c#

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;
}

Related

Serialize a JSON object without property name having a list of custom object in C#

I have model as below:
public class CustomModel
{
public string Data1 { get; set; }
public string Data2 { get; set; }
}
public class root
{
public List<CustomModel> data { get; set; }
}
My payload is as below:
List<CustomModel> cms = new List<CustomModel>();
CustomModel cm1 = new CustomModel();
cm1.Data1 = "a";
cm1.Data2 = "b";
cms.Add(cm1);
CustomModel cm2 = new CustomModel();
cm2.Data1 = "D";
cm2.Data2 = "E";
cms.Add(cm2);
BaseClass baseClass = new BaseClass();
baseClass.data = cms;
My JSON is:
var json = new JavaScriptSerializer().Serialize(baseClass);
And Result is:
{"data":[{"data1":"a","data2":"b"},{"data1":"D","data2":"E"}]}
BUT I need: without the "data" property as below:
{[{"data1":"a","data2":"b"},{"data1":"D","data2":"E"}]}
I tried the below function:
public static IEnumerable<object> GetPropertyValues<T>(T input)
{
return input.GetType()
.GetProperties()
.Select(p => p.GetValue(input));
}
Like
var value_only = GetPropertyValues(baseClass);
var json = new JavaScriptSerializer().Serialize(value_only);
BUT it returns [[{"data1":"a","data2":"b"},{"data1":"D","data2":"E"}]]
Is there anywasy to do it other than manually adding? Please help.
Note that {[{"data1":"a","data2":"b"},{"data1":"D","data2":"E"}]} is not valid json. In Json objects, data/values are organized by (named) properties.
However, here you seem to want a (root) Json object containing a value being Json array, but that value is not associated with a Json object property, thus not being valid Json.
If you really want invalid Json, i suggest you serialize the List<CustomModel> instance instead of the root model instance, resulting in a Json array, and then manually adding the surrounding { and } to the serialized Json string, thus giving you your desired invalid Json result:
var json = new JavaScriptSerializer().Serialize(baseClass.data);
var desiredResult = "{" + json + "}";
you don't need root class (or base class you must to deside what is name. Just use
var json = new JavaScriptSerializer().Serialize(cms);
PS.
And it is time to select a modern serializer.

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;

Deserialize raw JSON and convert to custom C# Object

I have the following raw JSON string:
[\"Hello World!\",\"94952923696694934\",\"MyChannel\"]
I have tried the following without luck:
My custom object class:
public class MyObject
{
public string msg { get; set; }
public string id { get; set; }
public string chn { get; set; }
}
JSON string:
string str = "[\"Hello World!\",\"94952923696694934\",\"MyChannel\"]";
1st attempt at deserilization using System.Web.Script.Serialization:
JavaScriptSerializer serializer = new JavaScriptSerializer();
MyObject obj1 = serializer.Deserialize<MyObject>(str);
2nd attempt at deserilization using Newtonsoft.Json:
MyObject obj2 = JsonConvert.DeserializeObject<MyObject>(str);
Both attempts fail. Any suggestions?
You have a JSON array of strings, not an object with property names.
So the best you can do here is to deserialize the array:
IEnumerable<string> strings =
JsonConvert.DeserializeObject<IEnumerable<string>>(str);
...then use the resulting sequence strings as you see fit.
With PubNub, you can just pass in the native String, Dictionary, or Array, and we'll JSON encode it for you on the publish side, and auto JSON decode for you on the subscriber side.
It's because your 'custom object' isn't equivalent to the json representation. The json you're deserializing is just a string[] in C# (you can also use List<string> or other IEums).
So in code you're looking for;
string[] theJson = JsonConvert.DeserializeObject<string[]>(str);
MyObject would be used for the following json;
{
"msg":"Hello World!",
"id":"94952923696694934",
"chn":"MyChannel"
}

How to parse non-array JSON?

I am trying to read json from a local .json file and parse the contents using StreamReader and Json.NET. Json & my code:
contents of .json file: {"rate":50,"information":{"height":70,"ssn":43,"name":"andrew"}}
using (var sr = new StreamReader(pathToJsonFile))
{
dynamic jsonArray = JsonConvert.DeserializeObject(sr.ReadToEnd());
foreach(var item in jsonArray)
{
Console.WriteLine(item.rate);
Console.WriteLine(item.ssn);
}
}
This gives me an error on the line foreach(var item in array): Object reference not set to an instance of an object. I am guessing this is because my json is not actually an array but that is how I am trying to parse it. How can I parse this json in order to pull out fields such as rate or ssn?
NB - please do not flag this question as a duplicate of Read and parse a Json File in C#, as that is where I got my original code from.
EDIT: As has been pointed out in other answers, jsonArray is null. That explains my error but still does not answer my question. How else can I parse this json in order to extract the desired fields?
A couple things:
If you want to manually parse out the values, you should try using JObject rather than JsonConvert.DeserializeObject. The following code should work:
dynamic jsonObject = JObject.Parse("{'rate':50,'information':{'height':70,'ssn':43,'name':'andrew'}}");
Console.WriteLine(jsonObject["rate"]);
Console.WriteLine(jsonObject["information"]["ssn"]);
However, if you know how the json is structured, you should create a .net class like:
public class Person
{
public int rate {get;set;}
public Information information {get;set;}
}
public class Information
{
public int height {get;set;}
public int ssn {get;set;}
public string name {get;set;}
}
and then use:
var person = JsonConvert.DeserializeObject<Person>(thestringtodeserialize);
That way you can have a strongly typed object.
In any case, I would check for null (DeserializeObject can obviously return null):
using (var sr = new StreamReader(pathToJsonFile))
{
dynamic jsonArray = JsonConvert.DeserializeObject(sr.ReadToEnd());
if(jsonArray != null) //new check here
{
foreach(var item in jsonArray)
{
Console.WriteLine(item.rate);
Console.WriteLine(item.ssn);
}
}
I am guessing this is because my json is not actually an array
True, the returned object is dynamic, so make use of dynamic:
var json = "{\"rate\":50,\"information\":{\"height\":70,\"ssn\":43,\"name\":\"andrew\"}}";
dynamic obj = JsonConvert.DeserializeObject(json);
Console.WriteLine("rate: {0}. ssn: {1}", obj.rate, obj.information.ssn);
See live sample here: https://dotnetfiddle.net/nQYuyX
Are you sure it's an array?
If that's the format the you expect from Json, maybe you should consider defining a class.
For example:
class SomeJsonObject
{
public int rate {get;set;}
[JsonProperty("information")] //if you want to name your property something else
public InformationObject Information {get;set;}
}
class InformationObject
{
[JsonProperty("height", NullValueHandling = NullValueHandling.Ignore)] //some other things you can do with Json
public int Height {get;set;}
public int ssn {get;set;}
public string name {get;set;}
}
This way you can just deserialize it to an object:
SomeJsonObject jsonArray = JsonConvert.DeserializeObject<SomeJsonObject>(sr.ReadToEnd());
I think your question is similar to this Deserialize JSON with C# . you can use JavaScriptSerializer
I don't get a null reference (with Json.net 6.0.3) but your code has one obvious bug:
static void Main(string[] args)
{
string s = "{'rate':50,'information':{'height':70,'ssn':43,'name':'andrew'}}".Replace('\'', '\"');
var obj = JsonConvert.DeserializeObject(s);
dynamic jsonArray = obj;
foreach (var item in jsonArray)
{
Console.WriteLine(item.rate);
Console.WriteLine(item.ssn);
}
}
The bug is Console.WriteLine(item.rate) will throw.
Your 'array' jsonArray is not actually an array, it is a dictionary!
Therefore, item=the first Key-Value-pair in the dictionary, = {"rate":50}.
You can prevent the code from throwing by getting rid of your foreach loop.
i would fire up nuget and get the JSON.net package
https://www.nuget.org/packages/Newtonsoft.Json/
http://james.newtonking.com/json
it is well documented and can save you a tonne of work.
see also http://json2csharp.com/
EDIT: you are already using this

Error in creating xml from an list of mock objects

I wanted to generate a sample xml so I write a unit test in which I have created an object using moq. I tried to serialize it like this:
private AssetDescription GetAssetDescription(string description, string type, string name, string iconUrl)
{
var asstDesp = new Mock<AssetDescription>(type);
asstDesp.Setup(m => m.Description).Returns(description);
asstDesp.Setup(m => m.Type).Returns(type);
asstDesp.Setup(m => m.Name).Returns(name);
asstDesp.Setup(m => m.IconUrl).Returns(iconUrl);
return asstDesp.Object;
}
Note: here AssetDescription is a class like this:
[DataContract]
public class AssetDescription
{
[DataMember]
public virtual string Type { get; set; }
[DataMember]
public virtual string Name { get; set; }
[DataMember]
public virtual string Description { get; set; }
[DataMember]
public virtual string IconUrl { get; set; }
public AssetDescription(string type)
{
Type = type;
}
public AssetDescription()
{
// I have added a parameter less constructor to xml serialization.
}
}
XML serialization method:
public string SerializeObject(object obj)
{
var xmlDoc = new XmlDocument();
var serializer = new XmlSerializer(obj.GetType());
using (var ms = new MemoryStream())
{
serializer.Serialize(ms, obj);
ms.Position = 0;
xmlDoc.Load(ms);
return xmlDoc.InnerXml;
}
}
Now I can serialize the AssetDescription successfully like this :
var ds = GetAssetDescription("Description1", "type1", "name1", "iconurl1");
var dsxml = SerializeObject(ds);
Problem: AssetDescription is a part of a list and that list is part of some other object I have created that object using moq. I have break down to this after some testing:-
I am not able to serialize a list of AssetDescription it is throwing error.
Here is my list creating method:
private List<AssetDescription> GetListAssetDescriptions()
{
var lst = new List<AssetDescription>
{
GetAssetDescription("Description1", "type1", "name1", "iconurl1"),
GetAssetDescription("Description2", "type2", "name2", "iconurl2"),
GetAssetDescription("Description3", "type3", "name3", "iconurl3"),
GetAssetDescription("Description4", "type4", "name4", "iconurl4")
};
return lst;
}
I tried to serialize it like this:
var fgh = GetListAssetDescriptions();
var fghd = SerializeObject(fgh);
but this error occurs:
There was an error generating the XML document
Questions:
can I generate xml from mock objects?
if yes, then does anybody know how to solve this error?
Not an answer, but I'm puzzled with this question. Let me ask you a few questions:
Why do you need mock there? AssetDescription is a POCO, not an interface. As far as your code goes, this class does not do anything. Why can't you just create a real object, not a mock?
If you need mock there, what is the purpose of serialisation to xml? what do you do with it later?
Mocks are for testing only. One must think really hard before adding a Moq reference to non-testing project. Mocks have quite complex internal structure - they are designed to pretend to be something they are not. XML serialisation was not part of design for these guys, so no surprise you can't serialise mock into XML. And I'll go that far and say that there is no work-around for this. Because mocks must not be serialised.

Categories