2016-09-13 153 views
1

我試圖抓取來自3家公司的最新股票價格,我似乎無法正確獲取數字。我可以得到我的符號刮谷歌金融和我得到一個類似的對象:反序列化Google Financial JSON字符串

// [ { "id": "983582" ,"t" : ".DJI" ,"e" : "INDEXDJX" ,"l" : "18,051.10" ,"l_fix" : "18051.10" ,"l_cur" : "18,051.10" ,"s": "0" ,"ltt":"3:15PM EDT" ,"lt" : "Sep 13, 3:15PM EDT" ,"lt_dts" : "2016-09-13T15:15:39Z" ,"c" : "-273.97" ,"c_fix" : "-273.97" ,"cp" : "-1.50" ,"cp_fix" : "-1.50" ,"ccol" : "chr" ,"pcls_fix" : "18325.07" } ] 

,我試圖抓住該項目的第四個冒號,這是「18,051.10」後,並抵消了休息和放將數值加倍到數組中,這樣我就可以返回並顯示給標籤,但沒有運氣。我是一個noob程序員,試圖修復一個示例程序,該程序返回了公司的股票圖表歷史記錄,但我只想返回最新的報價。

Imports System.Net 
Imports System.IO 
Imports System.Drawing.Drawing2D 

Public Class Form1 
' The ticker symbols. 
Private Symbols As List(Of String) = Nothing 

' The current prices. 
Private Prices() As List(Of Single) = Nothing 

' Redraw the graph. 
'Private Sub picGraph_Resize(ByVal sender As Object, ByVal e As System.EventArgs) 
' DrawGraph() 
'End Sub 

' Get the closing prices and graph them. 
Private Sub btnGo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGo.Click 
    Me.Cursor = Cursors.WaitCursor 

    ' Get the ticker symbols. 
    'Dim symbols_text() As String = txtSymbols.Text.Split(","c) 
    Dim symbols_text() As String = {"PKG", "TEN", "INDU"} 
    Symbols = New List(Of String)() 
    For i As Integer = 0 To symbols_text.Length - 1 
     Symbols.Add(symbols_text(i).Trim()) 
    Next i 

    ' Get the data. 
    ReDim Prices(0 To Symbols.Count - 1) 
    For i As Integer = 0 To Symbols.Count - 1 
     Prices(i) = GetStockPrices(Symbols(i)) 
    Next i 

    ' Graph it. 
    'DrawGraph() 
    FillData() 
    Me.Cursor = Cursors.Default 
End Sub 

' Get the prices for this symbol. 
'Private Function GetStockPrices(ByVal symbol As String) As List(Of Single) 
' ' Compose the URL. 
' Dim url As String = "http://www.google.com/finance/historical?output=csv&q=" & symbol 

' ' Get the result. 
' ' Get the web response. 
' Dim result As String = GetWebResponse(url) 

' ' Get the historical prices. 
' Dim lines() As String = result.Split(_ 
'  New String() {vbCr, vbLf}, _ 
'  StringSplitOptions.RemoveEmptyEntries) 
' Dim prices As New List(Of Single)() 

' ' Process the lines, skipping the header. 
' For i As Integer = 1 To lines.Length - 1 
'  Dim line As String = lines(i) 
'  prices.Add(Single.Parse(line.Split(","c)(4))) 
' Next i 

' Return prices 
'End Function 

Public Function GetStockPrices(symbol As String) As List(Of Single) 
    ' Dim pricesArray() As String 
    Dim prices As New List(Of Single)() 
    Dim items() As GoogleFinanceItem 

    If UCase(symbol) = "INDU" Then 
     Dim url As String = "http://finance.google.com/finance/info?client=ig&q=INDEXDJX%3A.DJI" 
     Dim result As String = GetWebResponse(url) 
     ' Dim newResult = result.Substring(1, result.Length - 1) 
     items = JsonConvert.DeserializeObject(Of GoogleFinanceItem())(result) 
     ' pricesArray = Split(result, ":") 
    Else 
     Dim url As String = "http://finance.google.com/finance/info?client=ig&q=" & UCase(symbol) 
     Dim result As String = GetWebResponse(url) 
     ' Dim newResult = result.Substring(1, result.Length - 1) 
     items = JsonConvert.DeserializeObject(Of GoogleFinanceItem())(result) 
     ' pricesArray = Split(result, ":") 
    End If 
    ' pricesArray = Split(pricesArray(4), """") 

    ' prices.Add(CSng(Format(pricesArray(1), "0.00"))) 
    'prices.Add(CSng(Format(pricesArray(1)))) 
    prices.Add(CSng(items(0).price)) 
    Return prices 

End Function 

' Get a web response. 
Private Function GetWebResponse(ByVal url As String) As String 
    ' Make a WebClient. 
    Dim web_client As New WebClient() 

    ' Get the indicated URL. 
    Dim response As Stream = web_client.OpenRead(url) 

    ' Read the result. 
    Using stream_reader As New StreamReader(response) 
     ' Get the results. 
     Dim result As String = stream_reader.ReadToEnd() 

     ' Close the stream reader and its underlying stream. 
     stream_reader.Close() 

     ' Return the result. 
     Return result 
    End Using 
End Function 

Private Sub FillData() 
    Dim symbolSubSet() As Control = {Label1, Label2, Label3} 
    Dim priceSubSet() As Control = {Label4, Label5, Label6} 

    For i = 0 To 2 
     symbolSubSet(i).Text = Symbols(i) 
     priceSubSet(i).Text = Prices(i).ToString 
     Next 
End Sub 
' Draw the graph. 
'Private Sub DrawGraph() 
' If (Prices Is Nothing) Then Return 

' ' Make the bitmap. 
' Dim bm As New Bitmap(_ 
'  picGraph.ClientSize.Width, _ 
'  picGraph.ClientSize.Height) 
' Using gr As Graphics = Graphics.FromImage(bm) 
'  gr.Clear(Color.White) 
'  gr.SmoothingMode = SmoothingMode.AntiAlias 

'  ' Get the largest prices. 
'  Dim max_price As Single = 10 
'  For Each symbol_prices As List(Of Single) In Prices 
'   Dim new_max As Single = symbol_prices.Max() 
'   If (max_price < new_max) Then max_price = new_max 
'  Next symbol_prices 

'  ' Scale and translate the graph. 
'  Dim scale_x As Single = -picGraph.ClientSize.Width/CSng(Prices(0).Count) 
'  Dim scale_y As Single = -picGraph.ClientSize.Height/max_price 
'  gr.ScaleTransform(scale_x, scale_y) 
'  gr.TranslateTransform(_ 
'   picGraph.ClientSize.Width, _ 
'   picGraph.ClientSize.Height, _ 
'   System.Drawing.Drawing2D.MatrixOrder.Append) 

'  ' Draw the grid lines. 
'  Using string_format As New StringFormat() 
'   Using thin_pen As New Pen(Color.Gray, 0) 
'    For y As Integer = 0 To CInt(max_price) Step 10 
'     gr.DrawLine(thin_pen, 0, y, Prices(0).Count, y) 
'    Next y 
'    For x As Integer = 0 To Prices(0).Count - 1 Step 7 
'     gr.DrawLine(thin_pen, x, 0, x, 2) 
'    Next x 
'   End Using 
'  End Using 

'  ' Draw each symbol's prices. 
'  Dim colors() As Color = {Color.Black, Color.Red, Color.Green, Color.Blue, Color.Orange, Color.Purple} 
'  For symbol_num As Integer = 0 To Prices.Length - 1 
'   Dim symbol_prices As List(Of Single) = Prices(symbol_num) 

'   ' Make the data points. 
'   Dim points(0 To symbol_prices.Count - 1) As PointF 
'   For i As Integer = 0 To symbol_prices.Count - 1 
'    points(i) = New PointF(i, symbol_prices(i)) 
'   Next i 

'   ' Draw the points. 
'   Dim clr As Color = colors(symbol_num Mod colors.Length) 
'   Using thin_pen As New Pen(clr, 0) 
'    gr.DrawLines(thin_pen, points) 
'   End Using 

'   ' Draw the symbol's name. 
'   DrawSymbolName(gr, Symbols(symbol_num), _ 
'    symbol_prices(symbol_prices.Count - 1), clr) 
'  Next symbol_num 
' End Using 

' ' Display the result. 
' picGraph.Image = bm 
'End Sub 

' Draw the text at the specified location. 
'Private Sub DrawSymbolName(ByVal gr As Graphics, ByVal txt As String, ByVal y As Single, ByVal clr As Color) 
' ' See where the point is in PictureBox coordinates. 
' Dim old_transformation As Matrix = gr.Transform 
' Dim pt() As PointF = {New PointF(0, y)} 
' gr.Transform.TransformPoints(pt) 

' ' Reset the transformation. 
' gr.ResetTransform() 

' ' Draw the text. 
' Using small_font As New Font("Arial", 8) 
'  Using br As New SolidBrush(clr) 
'   gr.DrawString(txt, small_font, br, 0, pt(0).Y) 
'  End Using 
' End Using 

' ' Restore the original transformation. 
' gr.Transform = old_transformation 
'End Sub 

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load 

    End Sub 
End Class 

我也有GoogleFinanceItem類

Imports Newtonsoft.Json 


Public Class GoogleFinanceItem 

Public Property id As String 
Public Property t As String 
Public Property e As String 
Public Property l As String 
<JsonProperty("l_fix")> 
Public Property price As String 
Public Property l_cur As String 
Public Property s As String 
Public Property ltt As String 
Public Property lt As String 
Public Property lt_dts As Date 
Public Property c As String 
Public Property c_fix As String 
Public Property cp As String 
Public Property cp_fix As String 
Public Property ccol As String 
Public Property pcls_fix As String 


End Class 

我試圖反序列化JSON和我傾倒JSON字符串轉化爲成果,並傳遞一個到解串器,並收到以下錯誤

Newtonsoft.Json.dll中發生類型爲「Newtonsoft.Json.JsonSerializationException」的未處理的異常

附加信息:無法反序列化當前的JSON對象(例如{「name」:「value」})轉換爲類型'howto_net_graph_stock_history.GoogleFinanceItem []',因爲該類型需要JSON數組(例如[1,2,3])才能正確地反序列化。

要修復此錯誤,請將JSON更改爲JSON數組(例如[1,2,3])或更改反序列化類型,以使其成爲正常的.NET類型(例如,不是像整數這樣的基本類型,不是像數組或List的集合類型),可以從JSON對象反序列化。 JsonObjectAttribute也可以添加到類型中,以強制它從JSON對象反序列化。

enter image description here

+0

如果您將JSON反序列化爲對象,則您將有更容易的時間。 – TyCobb

+0

谷歌反序列化似乎會更簡單。爲了做到這一點,我必須輸入什麼?我想試試這個,另一種方法就是看比較 – Edgar

回答

3

這不只是看中格式的字符串。這是一個JSON字符串,這意味着它可以被解析或反序列化爲一個對象,讓您可以輕鬆訪問所有信息。

首先,你想得到Newtonsoft's JSON parser。然後一個類來捕獲數據:

' see this link for the meaning of the other properties 
'https://www.quora.com/What-do-the-following-attributes-returned-in-a-JSON-array-from-the-Google-Finance-API-mean 
Public Class GoogleFinanceItem 
    Public Property id As String 
    <JsonProperty("t")> 
    Public Property Symbol As String 
    <JsonProperty("e")> 
    Public Property Index As String 
    <JsonProperty("l")> 
    Public Property LastTradePrice As Decimal 
    <JsonProperty("l_fix")> 
    Public Property LastPriceCurrency As Decimal 
    Public Property l_cur As String 
    Public Property s As String 
    Public Property ltt As String 
    Public Property lt As String 
    Public Property lt_dts As Date 
    <JsonProperty("c")> 
    Public Property Change As String 
    Public Property c_fix As String 
    Public Property cp As String 
    Public Property cp_fix As Decimal 
    Public Property ccol As String 
    Public Property pcls_fix As String 
End Class 

可以自動生成類是這樣的:

  1. 複製JSON到剪貼板
  2. 創建一個新的類文件
  3. 選擇編輯|選擇性粘貼|粘貼JSON作爲類

如果你有Visual Studio中的一個更老的版本,沒有這一點,你可以在http://jsonutils.com/使用機器人創建VB或者C#類。

我對機器人提出的類做了一些改動。 a)這些都是非常難看的屬性名稱。爲了將它們轉換爲更具描述性或可讀性的內容,您可以使用<JsonProperty("json name")>來告訴JSON.NET將其反序列化爲不同的屬性名稱。 b)我還將數字更改爲Decimal,因此可以在其他地方的數學中使用它們。

反序列化很容易,但還有一個額外的清理步驟。谷歌顯然寧願你使用他們的API,而不是自己使用響應,所以有一個領先的「//」。這需要修剪掉之前將反序列化:

Dim jstr = GetWebResponse(url).Replace("//", "") 

Dim items As GoogleFinanceItem() = JsonConvert.DeserializeObject(Of GoogleFinanceItem())(jstr) 

在這種情況下,它是一個的陣列,但該數據將通過屬性可用:

Console.Writeline(items(0).Ticker)) 

使用屬性網格查看該對象的屬性值:

enter image description here


未來[R讀者可能想要將多個引號放入DGV的列表中。目前還不清楚是否有方法在API之外的請求中請求多個引號。因此,使用一個循環:

Dim syms As String() = {"GOOG", "MSFT", "INTC"} 
GQuotes = New List(Of GoogleFinanceItem) 

Dim urlMask As String = "http://finance.google.com/finance/info?client=ig&q={0}" 
Dim url As String 

For Each s As String In syms 
    url = String.Format(urlMask, s) 
    Dim jstr As String = GetWebResponse(url).Replace("//", "") 
    Dim items = JsonConvert.DeserializeObject(Of GoogleFinanceItem())(jstr) 

    GQuotes.Add(items(0)) 
Next 

dgv1.DataSource = GQuotes 

如果列表很長,則可能有必要要求,以防止在發佈過短的時間太多的要求之間的短暫停頓。

enter image description here