Attach JSON data to be used by view in MVC application - json

I have a very simple application that I am using to learn move about MVC. In that application I search some data and return a JSON string that I want to use as the model for the view. I just can't seem to figure out how to get the view to consume the JSON as a set of data for it to show on screen.
The code I have so far:
Function Find(term As String) As ActionResult
Dim model As String = SearchData(term)
Return View(model)
End Function
SearchData returns a JSON string that can have one or many objects in it.
How do I now take the JSON returned from SearchData and use it in a view? In fact, when I attempt to add a view it wants to know what model to use. How do i also specific that?

Create a strongly typed object to store you data when parsed
Public Class Data
Public Property ID As Integer
Public Property Term As String
Public Property SomeProperty As String
Public Property SomeOtherProperty As String
End Class
Using a library like JSON.Net, parse the JSON returned from the search.
This assumes a collection of Data is returned from the search.
Imports Newtonsoft.Json;
Function Find(term As String) As ActionResult
Dim json As String = SearchData(term)
Dim model As List(Of Data) = JsonConvert.DeserializeObject(Of List(Of Data))(json)
Return View(model)
End Function
Let the view know to expect the strongly typed model.
#ModelType List(Of Data)
#Code
ViewData("Title") = "Find"
End Code
<h2>MyView</h2>
<!-- rest of view where model can be accessed -->

Related

How to deserialize Json with fix named elements dynamically in vb.net?

I’m on the way to implement an interface to the Ameritrade Rest API in a vb.net application (with httpclient).
Amongst other things, I have to query quotes from a ticker list (e.g. AMD,MSFT,AMZN, ....).
The call of the API works without problems, I get a valid Json back, but the Json is not given back in a way, I would expect.
I now search the best way to handle that problem...
This is not the first interface to a Rest API, I have implemented.
Normally, I implement a corresponding data class in vb.net and then use JsonConvert (from Newtonsoft) to deserialize the Json string into my data class.
Example:
Dim oObject As New DataClass
oObject = JsonConvert.DeserializeObject(Of DataClass)(JsonString)
whereby DataClass is the vb.net class that is defined according to the data in the Json string.
Problem:
The ticker symbol-list to query is dynamic and can change from api call to api call.
If I - e.g. - query AMD and MSFT in a call, I get back (cut to only a few fields) the following Json:
{
"AMD": {
"assetType": "EQUITY",
"symbol": "AMD",
"description": "Advanced Micro Devices, Inc. - Common Stock",
"bidPrice": 92.11
},
"MSFT": {
"assetType": "EQUITY",
"symbol": "MSFT",
"description": "Microsoft Corporation - Common Stock",
"bidPrice": 243.1
}
}
To be able to deserialize the Json, I would have to implement the following DataClass:
Public Class DataClass
Public Property AMD As AMD
Public Property MSFT As MSFT
End Class
Public Class AMD
Public Property assetType As String
Public Property symbol As String
Public Property description As String
Public Property bidPrice As Double
End Class
Public Class MSFT
Public Property assetType As String
Public Property symbol As String
Public Property description As String
Public Property bidPrice As Double
End Class
This would work but is absolutely static and does not make any sense, as I would have to implement a (identical) class for any ticker, I maybe want to query in the feature.
I would expect to get back a dynamic list so that I could implement the class as following:
Public Class DataClass
Public Property TickerDetails As List(Of TickerDetail)
End Class
Public Class TickerDetail
Public Property assetType As String
Public Property symbol As String
Public Property description As String
Public Property bidPrice As Double
End Class
This way, I would be able to deserialize in a List of TickerDetails and the go thru the list (no matter, which symbols I queried).
But, I can’t change, what I get back over the API...
Question:
What is the best way to handle this problem?
You should create a class to represent the a generic stock and then use DeserializeObject to deserialize it into a Dictionary(Of String, [classname]) where the Key represents the stock symbol and the value represents the class.
Take a look at this example:
Public Class Stock
Public Property assetType As String
Public Property symbol As String
Public Property description As String
Public Property bidPrice As Double
End Class
'...
Dim stocks = JsonConvert.DeserializeObject(Of Dictionary(Of String, Stock))(response)
Example: Live Demo
First thanks for the comments.
I ended up to do it completely different now...
I had further problems with the Ameritrade API:
Some fields are named with leading numbers (52WkHigh and 52WkLow) and
vb.net dev's know, that VB.net don't like properties in classes that
are named with a leading number
So I had to "patch" the received Json data and change the names on the fly to other names ("52WkHigh" to "dble52WkHigh" and "52WkLow" to "dble52WkLow") to be able to deserialize
over the data class, what is not nice
Further, I finally need the data (as fast as possible) in a data table and had "a long way to go":
get data -> deserialize to the data class -> walk thru the data class and overtake the data in the data table.
So.. my new solution (with JObject):
Note: needs:
Imports Newtonsoft.Json.Linq
Code snippets:
Create data table in memory:
Dim dtErgebnis As New DataTable
Dim drTemp As DataRow
With dtErgebnis.Columns
.Add("symbol", System.Type.GetType("System.String"))
.Add("lastPrice", System.Type.GetType("System.Double"))
.Add("lastSize", System.Type.GetType("System.Int32"))
.Add("quoteTime", System.Type.GetType("System.DateTime")) ' Note: is a Long in Json
...
End With
Parse the Json-String and fill the datatable:
get the data over httpclient (in JsonString)...
Dim oJson As JObject = JObject.Parse(JsonString) ' creates children tokens
Dim results As List(Of JToken) = oJson.Children().ToList
For Each item As JProperty In results
item.CreateReader()
drTemp = dtErgebnis.NewRow() ' create a new row to data table in memory
' Fill the fields
drTemp("symbol") = item.Value("symbol")
drTemp("lastPrice") = item.Value("lastPrice")
drTemp("lastSize") = item.Value("lastSize")
drTemp("quoteTime") = GetUTCDateFromTimeStamp(item.Value("quoteTimeInLong")).AddHours(1) ' original Long
...
' Add the new row to the data table
dtErgebnis.Rows.Add(drTemp)
' Save the changes
dtErgebnis.AcceptChanges()
Next
Additional note: The Ameritrade API gives back the time stamps as long (additional hurdle), but I (and I think also you;-) want it as datetime.
Therefore the Long (I think this data type comes from Java/Unix) has to be "translated" to datetime = vb.net function GetUTCDateFromTimeStamp below:
Public Function GetUTCDateFromTimeStamp(TimeStamp As Long) As DateTime
Static startTime As New DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)
Return startTime.AddMilliseconds(TimeStamp)
End Function
Additional note:
As I want to have the Swiss time, I add one hour to the UTC time.
So.. this a real good solution for me (exactly for the Ameritrade API).
And.. it's blazing fast... (I get 19 tickers with all fields and show the result (data table) in a data grid).
All together took < 1 Second ("felt" about 500 ms)
Hope this helps somebody...

JSON - Conversion to VB.NET Object

I am new to JSON strings so I am having a hard time with it.
I am used to SOAP Web Services where in Visual Studio automatically creates the strongly typed Classes for me in the background.
JSON - REST Web Services are for me is much tedious as I have to create manually the equivalent Strongly Typed Classes. (Or I maybe wrong).
I have this JSON String being returned to me by a REST Web Service:
{"Message":"The request is invalid.","ModelState":{"command":["Required property 'Vendor' not found in JSON. Path '', line 1, position 310."],"command.Terms":["The Terms field is required."]}}
Could you guide me on the equivalent Class?
Appreciate your help!
Regards,
Jake
assuming you are using JSON.NET...
Public Class Response
Public Property Message As String
Public Property ModelState As ModelState
End Class
Public Class ModelState
<JsonProperty("command")>
Public Property Command As List(Of String) = New List(Of String)
<JsonProperty("command.Terms")>
Public Property Terms As List(Of String) = New List(Of String)
End Class
Usage:
Dim response As Response = JsonConvert.DeserializeObject(jsonString)

Deserializing Json VB.NET

I am trying to deserialize data from a webserver for a game launcher.
The API docs provide me the data in json format, but I have been struggling to be able to read that data I am given and store it as a variable to use to log in a player. I have also tried a few other things but I am just stuck now. Normally a response from the server would like like this:
{"success":"true","gameserver":"gameserver-alpha.toontownrewritten.com","cookie":"deadbeefdeafbeef0x123"}
The code to deserialize the data:
Dim result() As TTRServerResponse = JsonConvert.DeserializeObject(Of TTRServerResponse())(responseFromServer)
Class with the variables I want to store
Public Class TTRServerResponse
Public Property success As String
Public Property eta As String
Public Property position As String
Public Property queueToken As String
Public Property cookie As String
End Class
Any ideas where I messed up or what I should do? Thanks, Ben.
EDIT: Finally figured it out, I needed to change my result to: Dim result As TTRServerResponse = JsonConvert.DeserializeObject(Of TTRServerResponse) (responseFromServer) I also was returning the data incorrectly to my other sub by returning just result. What I needed to do was return result.success. I now have a better understanding.
You are trying to deserialize the JSON into an array but in your example it is a single object.
So assuming
Dim responseFromServer As String
is equal to
{"success":"true","gameserver":"gameserver-alpha.toontownrewritten.com","cookie":"deadbeefdeafbeef0x123"}
Which, according to the documentation you linked to, is suppose to be a single object,
then you need to update your code to deserialize a single object as appose to an array
Dim result As TTRServerResponse = JsonConvert.DeserializeObject(Of TTRServerResponse)(responseFromServer)

Parsing JSON Objects within JSON arrays within JSON Objects in VB.Net

Hello Everyone and thanks for looking at this. I'm relatively new to vb.net and extremely new to parsing json in vb. I am using JSON.Net and I'm looking to gather data from the following JSON.
http://hastebin.com/bagiyetece.apache
I have classes created for each of the "sections". I am unsure of the correct terminology.
Class One:
Public Class StatsWrapper
Public SummonerID as Long
Public PlayerStatSummaries as playerStatSummaryTypeWrapper
End Class
Class Two:
Public Class playerStatSummaryTypeWrapper
Public playerStatSummaryType As String
Public wins As Long
Public modifyDate As Long
Public aggregatedStats As aggregatedStatsWrapper
End Class
Class Three:
http://hastebin.com/qopanafabe.php
My end goal is to be able to get elements like "totalChampionKills" for the playerStatSummaryType of "Cap5x5" and insert them into a datagridview.
I've been able to correctly parse the following JSON simply by using JObject.Parse.
{"UserName":{"id":84737282,"name":"UserName","profileIconId":660,"summonerLevel":30,"revisionDate":1455686689000}}
To get the id object, I would use:
Dim JSONDerulo = JObject.Parse(JSONResponse)
Dim SummonerID = JSONDerulo(LCase(ToolStripTextBox1.Text))("id")
Where the ToolStripTextBox1.Text is the UserName.
When I try to apply the same logic as above to the larger JSON file in a different sub:
Dim JSONDerulo = JObject.Parse(JSONResponse)
Dim PlayerStatSummaries = JSONDerulo("playerStatSummaries")
Dim Jarray As JArray = PlayerStatSummaries
I can do something like:
For Each obj As JObject In Jarray
TextBox2.Text = TextBox2.Text + Environment.NewLine + obj.ToString + Environment.NewLine
Next
Or call Jarray(1) and parse that again but the list of game types is going to be different for each UserName. I do have a master list for every game type though:
AramUnranked5x5, Ascension, Bilgewater, CAP5x5, CoopVsAI, CoopVsAI3x3, CounterPick, FirstBlood1x1, FirstBlood2x2, Hexakill, KingPoro, NightmareBot, OdinUnranked, OneForAll5x5, RankedPremade3x3, RankedPremade5x5, RankedSolo5x5, RankedTeam3x3, RankedTeam5x5, SummonersRift6x6, Unranked, Unranked3x3, URF, URFBots
If I want to (for example) call AramUnranked5x5.TotalChampionKills or something similar would I have to create a class for each type?
Any suggestions or ideas?
Thanks Again
Note: the json posted is considerably shorter and simpler than the gruesome aggregatedStatsWrapper class linked to depicts! Without data, I cant say whether it is right or not.
Since the aggregatedStats is its own type, nothing very interesting will show for it in a DataGridView, just the type name. There are several ways to handle this. One is to hide the property from the DGV, then when they change selected/current rows, find the new one in the list and set player.aggregatedStats as the selected object in a property grid for a master-detail type view. Playerstatsummary:
Public Class Playerstatsummary
Public Property playerStatSummaryType As String
Public Property wins As Integer
Public Property modifyDate As Long
<Browsable(False)>
Public Property aggregatedStats As Aggregatedstats
Public Property losses As Integer
End Class
<Browsable(False)> will result in the TypeName not being shown in a DGV:
Dim jstr = File.ReadAllText("C:\Temp\myjsonfilename")
Dim jobj = JObject.Parse(jstr)
Dim players = JsonConvert.DeserializeObject(Of List(Of Playerstatsummary))(jobj("playerStatSummaries").ToString)
By Parsing it first, you can skip that outer container. jobj("playerStatSummaries").ToString passes the property data to be deserialized into a List.
You can display what you have very easily without having to loop at all:
dgv1.DataSource = players
It wont yet know about Aggregatedstats unless and until you work out that class exactly. Until then, the type name will display. The post mentions being interested in Cap5x5 only. In that case, a PropertyGrid might be a better UI mechanism (after you find that guy in the list). Result:
(This is from before I added <Browsable(False)> to the class). You could show aggregatedStats as detail like this:
Private Sub DataGridView1_SelectionChanged(...etc
If DataGridView1.SelectedRows.Count = 0 Then Return
Dim thisOne = DataGridView1.SelectedRows(0).Cells(0).Value.ToString
Dim player = players.FirstOrDefault(Function(f) f.playerStatSummaryType = thisOne)
If player IsNot Nothing Then
PropertyGrid1.SelectedObject = player.aggregatedStats
End If
End Sub
In case you are wondering, the date is almost certainly a Unix Epoch date, easily converted to .NET.

Json deserialization multiple object

I got the problem deserializing the object.
Currently I have two objects that need to be deserialized but I only can input one. How to I achieve that?
Here my code:
Public Function PostContract(ByVal data As String) As String Implements IEchoTest.PostContract
Dim biz As New ContractBiz
Dim response As New ContractModel.ContractResponse
Dim request As String = data
'[Convert to entity data and pass to Business Layer]
response = biz.CreateContract(JsonConvert.DeserializeObject(Of Contract)(request))
Return JsonConvert.SerializeObject(response)
End Function