How to deserialize json string to a domain object? - c#

I am trying to convert the following json into a domain object .
JSON:
[{"name":"McDonalds","deals":[{"desc":"Onion Rings free with Double Cheese burgers"}],"geometry":{"lat":13.073412,"lng":80.221393}},{"name":"JusSportz","deals":[{"desc":"20% off on Wilson Rackets"}],"geometry":{"lat":13.073231,"lng":80.221181}}]
Model:
[DataContract]
public class Deal
{
[DataMember(Name="name")]
public string Store { get; set; }
[DataMember(Name="deals")]
public Offer[] Offers {get; set;}
[DataMember(Name="geometry")]
public GeoCoordinate Location { get; set; }
}
[DataContract]
public class Offer
{
[DataMember]
public string deal;
}
I tried the DataContractJsonSerializer that is in the System.Runtime.Serialization.Json namespace and there is apparently no way to convert a string into an object. Are there any other libraries which allow me to get this done? Or is there a way to get this done using this library (by converting the Json string to some intermediate format.)?

Here's how I deserialize JSON back to my domain objects.
using (var reader = new MemoryStream(Encoding.Unicode.GetBytes("YourStringValue")))
{
var ser = new DataContractJsonSerializer(typeof(Deal));
return (Deal)ser.ReadObject(reader);
}
Is this what you were looking for?

Try to change a bit Model:
[DataContract]
public class Deal
{
[DataMember(Name="name")]
public string Store { get; set; }
[DataMember(Name="deals")]
public Offer[] Offers {get; set;}
[DataMember(Name="geometry")]
public GeoCoordinate Location { get; set; }
}
[DataContract]
public class Offer
{
[DataMember(Name="desc")]
public string deal { get; set; }
}

Related

Deep copy - choosing the properties to copy

I would like to do a deep copy of an object. This object has some normal string, int, properties but it would also have custom objects (e.g. a list of custom objects).
Is there a way to do a deep copy where I pick and choose which properties to copy?
e.g. I want to copy
public class BankAccount
{
[Required]
[DeepCopy]
public string Number { get; }
[Required]
[DeepCopy]
public string Owner { get; set; }
[Required]
[DeepCopy]
public decimal Balance { get; }
[Required]
[DeepCopy]
public List<CustomAddress> {get; set;}
[Required]
public List<CustomLinkedAccounts> {get; set;}
}
Where perhaps I would want to copy everything except the List of CustomLinkedAccounts.
This is a solution I have used in the past for deep cloning.
It requires Newtonsoft JSON library.
It can be adapted to use System.Text.Json if you can't use third party libraries.
using Newtonsoft.Json;
public class BankAccount
{
[Required]
public string Number { get; }
[Required]
public string Owner { get; set; }
[Required]
public decimal Balance { get; }
[Required]
public List<CustomAddress> {get; set;}
[Required]
[JsonIgnore]//this is not in the json
public List<CustomLinkedAccounts> {get; set;}
public BankAccount Clone()
{
var json = JsonConvert.SerializeObject(this);
var result = JsonConvert.DeserializeObject<BankAccount>(json);
//this is a deep copy... no reference issues
return result;
}
}

Deserialize Objects with JsonConvert Class

I have a weird issue and am confused.
I have 3 class:
public class ProductInfo
{
public List<PartInfo> PartInfos { get; set; }
public string Name { get; set; }
}
public class SubProductInfo : PartInfo
{
public ProductInfo ProductInfo { get; set; }
}
public class PartInfo
{
public string Name { get; set; }
public string Desc { get; set; }
}
I have some information for industrial products. each product has some part and some sub product. for each product I have an object from type 'ProductInfo'. for each part related to this product I have an object of type 'PartInfo' and for each sub product related to this product I have an object of type 'SubProductInfo'. this 'ProductInfo' object serialized with 'JsonConvert.SerializeObject' method.
Example for serialized information:
{"PartInfos":[{"Name":"Part1","Desc":"Part1's Desc"},{"ProductInfo":{"PartInfos":[{"Name":"SubProduct1's Part1","Desc":"SubProduct1's Part1 desc"},{"Name":"SubProduct1's Part2","Desc":"SubProduct1's Part2 desc"}],"Name":"SubProduct1"},"Name":"SubProduct1 Details","Desc":"SubProduct1's Desc"}],"Name":"Product1"}
now I want to deserialize these JSONs to orginal object. I used:
JsonConvert.DeserializeObject<ProductInfo>(serializedObject)
but in deserialization 'SubProductInfo' objects will deserialize to 'PartInfo' objects.
how I can deserialize these JSONs to Exactly orginal objects?
Check out this: https://www.newtonsoft.com/json/help/html/SerializeTypeNameHandling.htm
When you're serializing, the protocol you're using usually has manners to solve problems like this, usually by type hinting. Basically your serialized product contains data that tells the deserializre which type to use when deserializing.
Like I commented, I really don't undestand what you are trying to achieve.
I think you want to make a list of SubProductInfo instead of PartInfo, as PartInfo is the base of SubProductInfo. Like this:
public class ProductInfo
{
public List<SubProductInfo> PartInfos { get; set; }
public string Name { get; set; }
}
public class SubProductInfo : PartInfo
{
public ProductInfo ProductInfo { get; set; }
}
public class PartInfo
{
public string Name { get; set; }
public string Desc { get; set; }
}
If a SubProductInfo is something different than a PartInfo and both need to be part of you ProductInfo class, you should keep seperate lists:
public class ProductInfo
{
public List<PartInfo> PartInfos { get; set; }
public List<SubProductInfo> SubProductInfos { get; set; }
public string Name { get; set; }
}
public class SubProductInfo : PartInfo
{
public ProductInfo ProductInfo { get; set; }
}
public class PartInfo
{
public string Name { get; set; }
public string Desc { get; set; }
}
Maybe you should avoid inheritence, it helps visualizing your data model.
Edit
The second option won't (de)serialize as SubProductInfo has a circular connection to ProductInfo. You can mark the ProductInfo property as not serializeble and fill it after reading it from json. Or just remove it, since the code that wants to use it should have access to the parent ProductInfo class.

.Net Parse JSON from Google

So I am using one of the google Id API; https://developers.google.com/instance-id/reference/server#manage_registration_tokens_for_push_subscriptions
I have previously been fortunate to have API that had WDSL or similar and been easy to parse into a class.
But the JSON I got back I can not parse easily.
{
"connectDate":"2018-02-12",
"application":"com.chrome.windows",
"subtype":"wp:https://xxxxxxxxxxxxxxxxxxx",
"authorizedEntity":"xxxxxx",
"rel":{
"topics":{
"movies":{
"addDate":"2018-01-26"
},
"anotherTopic":{
"addDate":"2018-02-12"
}
}
},
"connectionType":"WIFI",
"platform":"WEBPUSH"
}
Movies and anotherTopics are the topics I created so I can't add them to my class . Or can I?
There are of course ways to do it treating the json as string and using regex or going through the node as a dynamic object (dynamic dyn = JsonConvert.DeserializeObject(content);) but ideally I think it should be a dictionary (I think at least) but can not see how.
And as this is Google I assume there is more standard way to handle this kind of JSON.
I have tried creating a dictionary which I couldn't get working.
Stepping through the nodes I can get the data but end up with code like
DateTime.Parse(((Newtonsoft.Json.Linq.JValue)((Newtonsoft.Json.Linq.JProperty)((Newtonsoft.Json.Linq.JContainer)(obj.First)).First).Value).Value.ToString())
I have tried to look for similar JSON parsing exampels but I can not find any.
I did not share my attempt to extract the data in my first edit as I don't think that is the way to do it; it is a hack.
I created a class for it
public class SubscriptionDetails
{
public DateTime connectDate { get; set; }
public string application { get; set; }
public string subtype { get; set; }
public string authorizedEntity { get; set; }
public string connectionType { get; set; }
public string platform { get; set; }
public topics rel { get; set; }
}
But I am stuck when it comes to defining the subclass topics.
So I tried
public class topics : Dictionary<string, object>
which results in one dictionary entry with key topics?
the other option requires a dictionary name
public class topics
{
public Dictionary<string, Dictionary<string, string>> DUMMY { get; set; }
}
So thanks to the suggestion from Jamiec I got on the right track.
Of course already the node rel is a dictionary with one item called topics.
So need a few classes to parse the entire thing:
public class SubscriptionDetails
{
public DateTime connectDate { get; set; }
public string application { get; set; }
public string subtype { get; set; }
public string authorizedEntity { get; set; }
public string connectionType { get; set; }
public string platform { get; set; }
public Dictionary<string, topicItems> rel { get; set; }
}
public class topicItems : Dictionary<string, topicData> { }
public class topicData
{
public DateTime addDate { get; set; }
}
But if they add another node to rel in addition to 'topics' this most likely will crash.
Just doesn't seem to be a very good way to structure the data and the deserialised class isn't very user friendly either..
Anyway it works (for now)

Serialize object into JSON but only include properties with the [DataMember] attribute

How can I serialize the given object into JSON but only include properties with the [DataMember] attribute.
User MyUser = new User();
string MessageJson = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(MyUser);
public class User
{
[DataMember]
public string username { get; set; }
public string password { get; set; }
}
You need to use DataContractJsonSerializer for that.
Note that, I think you'll also need DataContract attribute on the class.
You can use JSON.Net.
If a class has many properties and you only want to serialize a small subset of them then adding JsonIgnore to all the others will be tedious and error prone. The way to tackle this scenario is to add the DataContractAttribute to the class and DataMemberAttributes to the properties to serialize. This is opt-in serialization, only the properties you mark up with be serialized, compared to opt-out serialization using JsonIgnoreAttribute.
[DataContract]
public class Computer
{
// included in JSON
[DataMember]
public string Name { get; set; }
[DataMember]
public decimal SalePrice { get; set; }
// ignored
public string Manufacture { get; set; }
public int StockCount { get; set; }
public decimal WholeSalePrice { get; set; }
public DateTime NextShipmentDate { get; set; }
}
You can place the [ScriptIgnore] attribute on the properties that you do not want to include in your result.

Deserializing json issue - inherited linq2SQL object

I have used Linq-to-SQL objects in my web app. My base and inherited classes look like this:
//Base Class: this will define the attributes that is auto-generated
//when using Linq-2-SQL ORM. Note this class is a partial class
[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.Categories")]
[global::System.Runtime.Serialization.DataContractAttribute()]
public partial class Category : INotifyPropertyChanging, INotifyPropertyChanged
//Inherited Class:
[Serializable]
public class CategoryEntity : Category
{
private int _ActiveAdsCount;
public int ActiveAdsCount
{
get
{
return _ActiveAdsCount;
}
set
{
_ActiveAdsCount = value;
}
}
public int DisplaySequence { get; set; }
}
when serialize, the Json OUTPUT is (note the ActiveAdsCount and DisplaySequence values):
[{"ActiveAdsCount":3429,"DisplaySequence":99,"CategoryID":636,"ParentCategoryID":635,"CategoryName":"propForRent","CategoryImageFN":null}]
When I am calling the deserialze object method
result = JsonConvert.DeserializeObject<T>(responseText);
where T is List
Result: it shows "ActiveAdsCount" and "DisplaySequence" have 0 values while the json shows proper correct information coming from Database. So, the problem is in deserialization.
I am using 4.5.1 version of Newtonsoft.Json.dll of .Net 4.0 framework
Moreover, I have marked my CategoryEntity class with DataContract attribute and its members to Datamember for serialization purpose. I notice that the Serialization attribute is making only the instance as serializable but not its members. So, the new class look like this:
[DataContract]
public class CategoryEntity : Category
{
[DataMember]
public int ActiveAdsCount { get; set; }
[DataMember]
public int DisplaySequence { get; set; }
[DataMember]
public IList<CategoryEntity> SubCategories { get; set; }
[DataMember]
public IList<BasicCategoryInfo> SubCategoriesBasicInfoList { get; set; }
[DataMember]
public string ParentCategoryNameEn { get; set; }
[DataMember]
public int CityID { get; set; }
}
#JasonJong Thanks very much for your comment.

Categories

Resources