I wish to read the entire contents of my appsettings.json file into NewtonSoft.JSON so I can parse it using NewtonSoft.
This is due to being able to use full JSON paths with NewtonSoft (filtering etc.)
I basically want to just read my entire appsettings.json file as a string.
I already have it working in regardings to a Configuration.
Private Shared Function InitConfig() As IConfigurationRoot
Try
Dim builder = New ConfigurationBuilder() _
.AddJsonFile("appsettings.json", True, True) _
.AddEnvironmentVariables()
Return builder.Build
Catch ex As Exception
Console.WriteLine(ex.Message)
Return Nothing
End Try
End Function
However I don't want to choose specifics i.e. config("test1:test:bot_token"). I wish to just read the entire string, however I don't appear to be able to get this from the ConfigurationRoot.
Cheers
Went about this all the wrong way - just used a streamreader to read the appsettings.json file.
Complete brain fart moment.
Dim tr As TextReader = New StreamReader("appsettings.json")
Dim stream = tr.ReadToEnd
This is my first dealing with JSON and unfortunately I have to do it in VB.Net, company policy. So I have searched high and low and tried a lot of examples even converted some of the C# code to VB.Net but I can't seem to find a complete solution.
I receive a JSON string like this:
{
"65080007":{
"partNo":"ATD000007",
"description":"Swingarm Hat Platform",
"quantity":4,
"assemblyseq":""
},
"65080143":{
"partNo":"ATD000143",
"description":"ASY Gas Spring Bracket",
"quantity":2,
"assemblyseq":""
},
"65080071":{
"partNo":"ATD000071",
"description":"TT Gas Spring",
"quantity":2,
"assemblyseq":""
},
"65080147":{
"partNo":"ATD000147",
"description":"ASY Lateral Hinge",
"quantity":8,
"assemblyseq":""
},
"65085181":{
"partNo":"RD0181",
"description":"ASY KIT Bolt, Carriage, 0.375 in x 16, 1.5 in (x45) & Nut, Flange, 0.375 in x 16 (x45)",
"quantity":1,
"assemblyseq":""
},
"65080796":{
"partNo":"ATD000796",
"description":"Decal, TT Equipped, Rectangular, 5 in x 10 in",
"quantity":1,
"assemblyseq":""
},
"65080797":{
"partNo":"ATD000797",
"description":"Decal, TT Open/Close, Triangular, 12 in x 8 in",
"quantity":1,
"assemblyseq":""
},
"65080745":{
"partNo":"ATD000745",
"description":"",
"quantity":1,
"assemblyseq":""
}
}
What I need to do bind or assign this data to a DataGridView.DataSource.
I've seen some examples but I can't set it as a DataSource.
I've tried this example:
Sub Main()
Dim json_result = GetJson()
Dim table = JsonConvert.DeserializeAnonymousType(json_result, (DataTable))
Dim newJString = Newtonsoft.Json.JsonConvert.SerializeObject(table, Newtonsoft.Json.Formatting.Indented)
Console.WriteLine("Re-serialized JSON: ")
Console.WriteLine(newJString)
Console.WriteLine("")
End Sub
Public Function GetJson() As String
Dim json_result As String = <![CDATA[
' I used the above json string
Return json_result
End Function
I have made my JSON classes to deserialise the JSON and tried JsonConvert.Deserialize keep getting an error it epected a array and found an object.
Public Class Jobs
'<JsonProperty("partno")>
Public Property PartNo As String
' <JsonProperty("description")>
Public Property Description As String
'<JsonProperty("quantity")>
Public Property Quantity As String
'<JsonProperty("assemblyseq")>
Public Property Assemblyseq As String
End Class
The issue I think is the root properties "65080797" these numbers will not be the same every time we get the JSON back from NetSuite.
So I tried to:
Dim obj = JsonConvert.DeserializeObject(Of Jobs)(result)
Console.WriteLine(obj.PartNo) it comes out PartNo = nothing
So I've tried this:
Dim resultA = JsonUtil.Deserialize(Of Jobs)(result, ignoreRoot:=True)
Module JsonUtil
Function Deserialize(Of T As Class)(ByVal json As String, ByVal ignoreRoot As Boolean) As T
Return If(ignoreRoot, JObject.Parse(json)?.Properties()?.First()?.Value?.ToObject(Of T)(), JObject.Parse(json)?.ToObject(Of T)())
End Function
End Module
This gives me the first group:
ATD000007
Swingarm Hat Platform
4
The assembly number was blank.
I'm open for any suggestions on how I can get the above JSON into a data table or DataGridView or how to make a list without the root "65080797" this number will be unique with every response.
The people that designed this response string refuses to remove the root properties.
Thank you for taking the time to read this mess.
All comments/suggestions are appreciated.
Yes, Json array looks like [something] instead of {somthing}, you could convert it to array if you want but you can also do it in different ways and even without any external library, you could create a datatable then bind it to datagridview or you could add data directly to datagridview.
Anyway, I made a datatable for you.
Imports System.Web.Script.Serialization 'for reading of JSON (+add the reference to System.Web.Extensions library)
Dim JSONC = New JavaScriptSerializer().Deserialize(Of Dictionary(Of String, Dictionary(Of String, String)))(JSON) 'you could do it in different ways too
Dim NewDT As New DataTable
'Create Columns
For Each key In JSONC.First.Value.Keys
'"65080007" <first
'{ "partNo":"ATD000007", "description":"Swingarm Hat Platform", "quantity":4, "assemblyseq":"" } <first.value
' "partNo" <first.value.key(s) :"ATD000007" <first.value.value(s)
NewDT.Columns.Add(key)
Next
'Add Rows
For Each item In JSONC
NewDT.Rows.Add(item.Value.Values.ToArray)
Next
DataGridView1.DataSource = NewDT
If you have unusually structured JSON like that, your best bet is probably to resort to using raw JObject and JToken handling instead of trying to get JSON.NET to deserialize into structured data automatically.
Create a method that will convert an individual JToken into the Job class you described in your question. I've added a Key property to identify those unique keys in the JSON that were problematic for you; if you don't need these, just remove the .Key bit from the example below.
Public Function CreateJob(data As JToken)
Return New Job With
{
.Key = data.Path,
.PartNo = data("partNo"),
.Description = data("description"),
.Quantity = data("quantity"),
.Assemblyseq = data("assemblyseq")
}
End Function
Once you have Job objects being created, you can walk the entire structure and turn it into an array of jobs with the sample code below.
Dim result As JObject = JsonConvert.DeserializeObject(json)
Dim jobs As Job() = result.Values().Select(Of Job)(AddressOf CreateJob).ToArray()
Once you have an array of Job objects, binding to a DataSource should be trivial.
A small question: i'm using JsonConverter from Github.
(https://github.com/VBA-tools/VBA-JSON/blob/master/JsonConverter.bas)
Code is working on most of the "GET" request.
Only when the same 'column' is accuring multiple times in the 'ResponseText' then it's not. (like "imei" in the example)
So I need a way to handle a long 'Responsetext' to fill multiple rows in an access db.
Dim Json As Object
Set Json = JsonConverter.ParseJson(xmlhttp.ResponseText)
MsgBox (Json("imei")) 'temp
Error 5: Invalid Procedure or Call Argument.
Any ideas?
Many thanks,
I can only provide a part of the answer, because I cannot recreate it, without the full JSON Response Text:
The response with mutliple values in JSON returns an Object of the type Collection. Hence you have to use a loop to iterate through all responses. Like this:
Dim Json As Object
Set Json = JsonConverter.ParseJson(xmlhttp.ResponseText)
For Each singleJsonItem In Json
'What object type is singleJsonItem? To find out, maybe use:
'MsgBox singleJsonItem("imei")
Next singleJsonItem
You have to find out the object type of the collectionentries to extract the JSON Entry.
Solved like this:
used : https://github.com/VBA-tools/VBA-JSON
and named the module: 'mdl_JsonConverter'
Set Json = mdl_JsonConverter.ParseJson(xmlhttp.ResponseText)
For Each item In Json
input_1 = item("input_1")
input_2 = item("input_2")
'THEN DO SOMETHING WITH VALUES F.E. ADDING THEM IN A TABLE
Next
If you responseText contains a searchRecords list then filter by searchRecords before for each
Set Json = JsonConverter.ParseJson(strResponse)
For Each singleJsonItem In Json("searchRecords")
'What object type is singleJsonItem? To find out, maybe use:
Msgbox singleJsonItem("Name")
Next singleJsonItem
I am having trouble separating pieces of a JSON object. Inside the json string there are 3 objects. One is called "JSONData", which I need to separate into its own object. I have tried so many things I'm starting to lose track. Two of which that seems to have been most helpful are below. However, they both end up empty. No errors, just empty. Hopefully someone can help!!
Dim j As String = JsonConvert.SerializeXmlNode(xml) 'Started out as XML
Dim o As JObject = JsonConvert.DeserializeObject(j) 'Then Json String to JObject
Dim channel As JObject = DirectCast(o("JSONData"), JObject) 'Try #1 to separate
'/// or
Dim jsondata As String = o.Item("JSONData") 'Try #2
'/// i have tried both above with ("IMSXMLLog.JSONData") as well. Same Result.
https://jsfiddle.net/jharris8567/v23kj42v/ - Full JSON
JSONData is inside another object IMSXMLLog, so your inclination to use the path IMSXMLLog.JSONData is correct. However, the indexer on JToken does not support paths, only single property names. To use path syntax you need to use the SelectToken method:
Dim data as JObject = DirectCast(o.SelectToken("IMSXMLLog.JSONData"), JObject)
Fiddle: https://dotnetfiddle.net/Wu70Tu
Let me explain: I want to make a currency converter form that uses online rates so that it's up to date. I plan to use Google, which has a currency converting function built in - type in:
[Any currency symbol][Any numeric amount] + in + [Any currency symbol]
I know how to format the URLs I will be searching for, and which class the span (whose text) I want is in, I simply just don't know how to programmatically take the result out and use it in my form.
Here's the applicable HTML code from a "£1 in $" conversion:
<div class="vk_ans vk_bk curtgt" style="padding-bottom: 4px">
<span style="word-break:break-all">1.68</span>
<span>US Dollar</span></div>
The class is called:
vk_ans vk_bk curtgt
The span text is the first one in the class (the one that contains "1.68")
BTW, I completely comprehend that there are easier-to-use API websites for this purpose, but I want to use Google because:
It will always be up
It's a good chance for me to learn how to grab a specific part a webpage.
I personnaly use http://www.nuget.org/packages/ScrapySharp/2.2.63 for html-scraping, it allows use to use CSS3 selectors to nicely grab what you need.
In your case it would be as simple as this :
Dim doc as HtmlAgilityPack.HtmlDocument = new HtmlAgilityPack.HtmlDocument()
doc.LoadHtml(GetRawHtml(theUrl))
Dim body as HtmlNode= doc.DocumentNode.SelectSingleNode("//body")
Dim yourSpan as HtmlNode = body.CssSelect(".vk_ans.vk_bk.curtgt").First()
dim yourValue as Double = Double.Parse(yourSpan.InnerText)
Function GetRawHtml(url As String) As String
Dim html As String = String.Empty
Dim request As WebRequest = WebRequest.Create(url)
Try
Using response As WebResponse = request.GetResponse()
Using data As Stream = response.GetResponseStream()
Using sr As New StreamReader(data)
html = sr.ReadToEnd()
End Using
End Using
End Using
Catch e As Exception
yourLogger.Error("WebRequest failed at url `{0}`. Error: {1}", url, e.ToString())
End Try
Return html
End Function
Also if the request is slow, you might want to change proxy attribute to nothing, see here : HttpWebRequest is extremely slow!