ASP.NET WebAPI 2 Nested JSON - c#

I've been stuck with this for a while and I can't seem to figure it out. Appreciate any help!
This is my model: http://www.jsoneditoronline.org/?id=9ee3466c40627f33c284e63544c8b8a7
I have the proper C# objects set up like this:
public class Media
{
public string name { get; set; }
public string title { get; set; }
public string album { get; set; }
public string artist { get; set; }
public string length { get; set; }
public int bitrate { get; set; }
public double size { get; set; }
public string start_time { get; set; }
public string mimetype { get; set; }
public string hash { get; set; }
}
public class Playlist
{
public string name { get; set; }
public List<Media> media { get; set; }
public List<Graphics> graphics { get; set; }
public bool shuffle { get; set; }
public int volume { get; set; }
public string start_time { get; set; }
public string end_time { get; set; }
}
public class Day
{
public string name { get; set; }
public List<Playlist> playlists { get; set; }
}
public class Schedule
{
public List<Day> days { get; set; }
public string hash { get; set; }
}
I need to POST this whole JSON object directly from the MVC Controller. On other occasions I'd like to PUT the schedule. How can I properly handle this? Examples could really help.
Thanks!
I'm already doing the below for POST:
var schedule = JsonConvert.DeserializeObject<Schedule>(model.ToString());
This is working as expected however, sometimes related Media objects already exist in the database and it is causing an Internal Server Error when trying to INSERT the same Media object (which already exists) - The [Key] for Media is the hash property.

You need to serialize Day class.
using Newtonsoft.json nuget package you need to serialize it as object. It will automatically serialize complex object to json
List<Day> days = // list of days result
var jsonData= JsonConvert.SerializeObject(days);
return json(jsonData);
Update
As per your update serialize and deserialize functions are working properly. You are facing issue while inserting records in Media.
Hash is not unique. and Hash Collision is possible. You need to improve hash generation code to use hash as identical.
Useful links to understand hash
what is hash ? is it unique?
Can 2 different string have the same hash code in C#
Socks, birthdays and hash collisions
Preventing Duplicates: Hash Table vs. Dictionary vs. Binary Search
Tree

You can use the extension method AddOrUpdate
using System.Data.Entity.Migrations;
db.Schedule.AddOrUpdate(schedule)

Related

C# DTO List that consists of 2 other lists

Firstly, apologies if this seems basic, I am new to C#/dotnet and if the answer to this questions is somewhere obvious please point me in the right direction.
I have a DTO class with the following code
public class LessonDetailView : BaseResult
{
public long Id { get; set; }
public string Title { get; set; }
public List<LessonImagesListView> LessonImages { get; set; }
public List<LessonInstructionCardListView> InstructionCards { get; set; }
}
public class LessonImagesListView
{
public long Id { get; set; }
public string Title { get; set; }
public ImageDetailView Image { get; set; }
public LessonImagesListView()
{
Image = new ImageDetailView();
}
}
public class LessonInstructionCardListView
{
public long Id { get; set; }
public string Instructions { get; set; }
}
So I have 2 distinct types of object that I attach to the lesson and send to the frontend.
I will add that in the future I might have 6 different types of object.
These Images, or Instructions are also going to be displayed in a certain order on the front end so instead of sending them all separately I wanted to combine them all and send them in a new List LessonAssetsListView for example.
How can i create Lists in a DTO that combine 2 other lists ?
OR ... is this something I even need to do here ... and can i just do all this in my service.
Help appreciated.
You could simply define a type that composes both your existing and send a List of them
public class LessonAsset
{
public LessonImagesListView Image {get;set; }
public LessonInstructionCardListView Instruction {get;set;}
}
and then
public class LessonDetailView : BaseResult
{
public long Id { get; set; }
public string Title { get; set; }
public List<LessonAsset> LessonAssets { get; set; }
}

Deserialize JSON objects one by one using json.net (XAMARIN)

I'm new to this. I'm using Xamarin in VS2017.
I have a JSON file as follows
[ {
"LEDGERID":1,
"LEDGERNAME":"CASH",
"UNDER":"19",
"CREDIT_PERIOD":"0",
"CREDIT_LIMIT":"0",
"LEDGER_TYPE":"DEBIT",
"OPENBAL":120196.00,
"STATUS":"True",
"USER_GEN":false,
"date":null,
"arabic_name":null},
{
"LEDGERID":2,
"LEDGERNAME":"PURCHASE",
"UNDER":"17",
"CREDIT_PERIOD":"0",
"CREDIT_LIMIT":"0",
"LEDGER_TYPE":"DEBIT",
"OPENBAL":0.00,
"STATUS":"True",
"USER_GEN":false,
"date":null,
"arabic_name":null
}
]
This is a lengthier one but i made it short for easy understanding. I need to take it one by one because sometimes I need to give test cases before taking the values to the list. I am using PCL storage in XAMARIN tostore the Json File. I went througn the documents of NewtonSoft Json deserializing. I hope some one can help me thanks in advance
Your json isn't valid, you had the word nul, however i'm sure it was a mistake
Take your json to http://json2csharp.com/ and create a class from it and call it what ever you want
Get your self the Json.net Nuget package
Example class
public class RootObject
{
public int LEDGERID { get; set; }
public string LEDGERNAME { get; set; }
public string UNDER { get; set; }
public string CREDIT_PERIOD { get; set; }
public string CREDIT_LIMIT { get; set; }
public string LEDGER_TYPE { get; set; }
public double OPENBAL { get; set; }
public string STATUS { get; set; }
public bool USER_GEN { get; set; }
public object date { get; set; }
public object arabic_name { get; set; }
}
Usage
var results = JsonConvert.DeserializeObject<List<RootObject>>(json);

Deserialize multiple JSON records in C# [duplicate]

This question already has an answer here:
Deserializing JSON into an object
(1 answer)
Closed 5 years ago.
I have the following string of Json records:
{
"records":[
{
"PK":"1_1_8",
"ID":"8",
"DeviceID":"1",
"RootID":"1",
"CustName":"test1",
"CustSurname":"test2",
"Address":"Nisou 1",
"City":"",
"ZipCode":"",
"PhoneNumber":"45646",
"HomePhoneNumber":"",
"Email":"",
"Notes":"",
"Owner":"1",
"LanguageID":"1",
"LanguagePK":"",
"DeletedFlag":"false",
"created":"2017-10-25 10:15:00",
"modified":"2017-10-25 09:35:43"
},
{
"PK":"1_1_33",
"ID":"33",
"DeviceID":"1",
"RootID":"1",
"CustName":"",
"CustSurname":"",
"Address":"",
"City":"",
"ZipCode":"",
"PhoneNumber":"",
"HomePhoneNumber":"",
"Email":"",
"Notes":"",
"Owner":null,
"LanguageID":"0",
"LanguagePK":"",
"DeletedFlag":"true",
"created":"2017-10-25 10:13:54",
"modified":"2017-10-25 10:13:54"
},
{
"PK":"1_1_16",
"ID":"16",
"DeviceID":"1",
"RootID":"1",
"CustName":"Theodosis",
"CustSurname":"",
"Address":"Dali",
"City":"Nicosia",
"ZipCode":"2540",
"PhoneNumber":"45645",
"HomePhoneNumber":"99123456",
"Email":"theodosis#gmail.com",
"Notes":"",
"Owner":"",
"LanguageID":"1",
"LanguagePK":"",
"DeletedFlag":"false",
"created":"2017-10-25 09:36:22",
"modified":"2017-10-25 09:36:22"
}
]
}
I am using Xamarin PCL in C# trying to parse this string into a list of objects.
I have a Customer class:
public class Customer
{
[PrimaryKey]
public string PK { get; set; }
public int DeviceID { get; set; }
public int ID { get; set; }
public string RootID{ get; set; }
public string CustName { get; set; }
public string CustSurname { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string ZipCode { get; set; }
public string PhoneNumber { get; set; }
public string HomePhoneNumber { get; set; }
public string Email { get; set; }
public string Notes { get; set; }
public bool Owner { get; set; }
public int LanguageID { get; set; }
public string LanguagePK { get; set; }
public bool DeletedFlag { get; set; }
public DateTime created { get; set; }
public DateTime modified { get; set; }
}
I also tried out having a container class with a list of Customer objects.
public class DataContainer
{
public List<Customer> customers { get; set; }
}
I have seen quite a few of examples online on how to parse this into a list or any workable type but nothing seems to be working for me.
I have tried the following (JsonResults holds the string of Json records):
var observation = JsonConvert.DeserializeObject<DataContainer>(JsonResults);
From other posts, I am not able to access JavaScriptSerializer class from my code, perhaps because of the Xamarin PCL Framework I am using.
Any ideas would be very welcome, as I said I do not mind the format I parse the string into, as long as it's workable.
Thank you.
You would have to make the following changes to your code to make this work.
First and most importantly, you don't have a property customers, you have records, so either rename it
public class DataContainer {
public List<Customer> records { get; set; }
}
or add a JsonProperty attribute
[JsonProperty(PropertyName = "records")]
Secondly, your Owner is a bool in C# and a nullable int (int?) in Json. So either change it in your C# class
public int? Owner { get; set; }
or write a converter to do that (e.g. like here)
[JsonConverter(typeof(NullableIntToBooleanConverter))]
public bool Owner { get; set; }
Here is a working .NetFiddle
The JSON string you provided is a JSON object, which contains a single property called records. records property is a List<Customer>. You can not deserialize the given string directly into DataContainer class that you provided because the property names do not match.
In the Class that your provided it is called customers
public class DataContainer {
public List<Customer> customers { get; set; } //records
}
Or please have a look at the attribute for a bit of advanced mapping
[JsonProperty]
JSON you provided is of the form:
{"records":[{Customer},{Customer},{Customer}]}
But Owner property is "1", null or "". Therefore I would suggest redefining Owner as int? (nullable)
Your string shows one object with a property named records that contains a list of other objects. Your code is trying to deserialize this into an object that doesn't have such a property.
Furthermore, the string contains objects with a property Owner that may be missing or have a numeric value. It's definitely not a bool.
You'll have to change Owner to :
public int? Owner { get; set; }
To deserialize the string, you need an object with a records property:
public class DataContainer
{
public Customer[] records { get; set; }
}
var data=JsonConvert.DeserializeObject<DataContainer>(json);
Debug.Assert(data.records.Length == 3);

How to: Nested Lists in SQLite-Net Extensions

How to: Do nested lists in sqlite-net-extensions
Answer Found: Keeping the question as an example of how to do it.
The problem i encountered was not sqlite-net-extensions related, but i'm keeping the question for context.
[Old Question]
I've got a problem with TwinCoders SQLite-net extensions.
I'm trying to insert a Series object into my database:
I'm using the Db.InsertWithChildren(SelectedSeriesObject,recursive:true) method.
The Series object is added accordingly with it's attributes.
All the Episodes are added as well, no problems there.
The problem is the BaseSeason.
It will only insert one Season object, which is (for some reason) the last Season Object of the list of Seasons in the Series
public class BaseSeries : BaseMedia
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
[Indexed]
public int ShowId { get; set; }
public string FirstAirDate { get; set; }
public string LastAirDate { get; set; }
public string Status { get; set; }
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<BaseSeason> Seasons { get; set; }
/// <summary>
/// TvShow = 0, Anime = 1
/// </summary>
public int SeriesType { get; set; }
}
public class BaseSeason
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
[ForeignKey(typeof(BaseSeries))]
public int SeasonId { get; set; }
public int SeasonNumber { get; set; }
public int NumberOfEpisodes { get; set; }
public string Plot { get; set; }
public string Poster { get; set; }
public string AirDate { get; set; }
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<BaseEpisode> Episodes { get; set; }
[ManyToOne]
public BaseSeries BaseSeries { get; set; }
}
public class BaseEpisode
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
[ForeignKey(typeof(BaseSeason))]
public int EpisodeId { get; set; }
public string Title { get; set; }
public string Plot { get; set; }
public string Poster { get; set; } //still path
public string AirDate { get; set; }
public int EpisodeNumber { get; set; }
public int SeasonNumber { get; set; }
public string SeriesName { get; set; }
[ManyToOne]
public BaseSeason BaseSeason { get; set; }
}
Is there anyone with experience regarding nested relationships in sqlite-net-extensions that knows how to make this work or see what i did wrong?
So regarding writing nested lists in sqlite-net-extensions:
My problem turned out the be related to how I handle the creation of these objects, this is by no means related to sqlite-net extensions. So my bad!
Which means that the questions example is valid and works. (I tested it of course)
Setting up the entities for the database:
The example shown in my question, with a Series class, Season class and Episode class, is the correct way of setting it up.
Inserting into the database:
If you're wondering how to insert an object similar to my Series object (with nested lists), use:
db.InsertWitchChildren(yourObject, recursion: true)
Here's an extended example:
public void AddSeries()
{
MediaDB.db.CreateTable<BaseSeries>();
MediaDB.db.CreateTable<BaseSeason>();
MediaDB.db.CreateTable<BaseEpisode>();
MediaDB.db.InsertWithChildren(SelectedSeries, recursion: true);
}
Side Note:
The example uses a static property on class with the connection string. Like so:
public class MediaDB
{
public static SQLiteConnection db => new SQLiteConnection(new SQLitePlatformGeneric(),"Media.db");
}
Refrain from doing this it is not really the best thing to do, since you should use using for the SQLiteConnection, making sure it's disposed once you're done with it.
more info on: sqlite-net-extentions
[UPDATE]: Further expansion of handling nested lists in sqlite-net extensions:
Deleting tables with children:
This is quite simple, but i spent a good hour and half figuring it out anyways.
Just use:
For lists/arrays: db.DeleteAll(yourCollection, recursion: true)
For single objects: db.Delete(yourObject, true);
As an exmaple: here's my implementation of a method that will delete a List
(BaseSeries is the class shown in the original question question):
public static void RemoveCollection<T>(List<T> collection)
{
using (db)
{
if (typeof(T) == typeof(BaseMovie))
{
db.DeleteAll(collection);
}
if (typeof(T) == typeof(BaseSeries))
{
db.DeleteAll(collection, recursion: true);
}
}
}
The BaseMovie class is a simple single entity, recursion is not needed since it holds no children.

WP8 JSON Deserialisation of Arrays nested in Arrays nested in Arrays

I want to do something quite simple.
I just want to take a JSON string (which I have) and populate a whole bunch of stuff with it.
The problem for me is that there are arrays hidden in array inside more arrays, and I can't get at my data.
I tried standard deserialization like so ...
var apiData = JsonConvert.DeserializeObject<RootObject>(json);
But this only lets me get into the top layer - what is in rootObject
I tried making a dictionary ...
Dictionary<string, dynamic> values = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(json);
but that doesn't let me drill down either (or I can't make it).
I have set up my c# using json2c#
I've been all over the internet including here.
The closest I have got to creating anything close is an expandoObject
var converter = new ExpandoObjectConverter();
dynamic obj = JsonConvert.DeserializeObject<ExpandoObject>(json, converter);
which I can see from the debugger is keeping everything structured as I would like but I've no idea how to get some of the stuff out.
Long story short, its been two days now and I'm bashing my head against a brick wall.
I just want to be able to get the data out of the JSON string and I can't change that string as its not mine.
public class NewsArticlesList
{
public string title { get; set; }
public string link { get; set; }
public string source { get; set; }
public string snippet { get; set; }
}
public class jobsList
{
public string title { get; set; }
public string titleLinkUrl { get; set; }
public List<object> relatedSearchesList { get; set; }
public string formattedTraffic { get; set; }
public int trafficBucketLowerBound { get; set; }
public int interestLevel { get; set; }
public string interestColor { get; set; }
public List<NewsArticlesList> newsArticlesList { get; set; }
public double startTime { get; set; }
public string shareUrl { get; set; }
public string date { get; set; }
}
public class jobsByDateList
{
public string date { get; set; }
public string formattedDate { get; set; }
public List<jobsList> jobsList { get; set; }
}
public class RootObject
{
public string summaryMessage { get; set; }
public double dataUpdateTime { get; set; }
public List<jobsByDateList> jobsByDateList { get; set; }
public string oldestVisibleDate { get; set; }
public bool lastPage { get; set; }
}
My problem is these lists inside lists inside lists.
I can get to jobsListByDate.formattedDate but I can't get anywhere near jobsListByDate.jobsList.titleLinkUrl let alone inside the NewsArticlesList to those sources.
Apologies if this is super-easy (I hope it is) but I'm a WP8 noob.
I know there are similar threads on SO, but none of them seem to deal with such deep arrays.
I was not stipulating which branch to go down and so it was confused.
System.Diagnostics.Debug.WriteLine(apiData.jobsByDateList[0].jobsList[0].interestLevel);
I was trying to get in using
System.Diagnostics.Debug.WriteLine(apiData.jobsByDateList.jobsList.interestLevel);
and intellisense was freaking out.
With the [0] I'm now able to drill in just fine and don't need the expandoobject. Just needed to sleep on it. :-)

Categories