从字符串在 VB.net 中创建 Json 并在 WebRequest 中使用它

Create Json in VB.net from string and use it in WebRequest

我正在尝试呼叫 openrouteservice api in vb.net and therefore tried to follow the documentation/examples。该示例显示以下代码作为工作示例:

Sub Main(args As String())
    Dim request = TryCast(System.Net.WebRequest.Create("https://api.openrouteservice.org/v2/directions/driving-car/gpx"), System.Net.HttpWebRequest)

    request.Method = "POST"

    request.Accept = "application/json, application/geo+json, application/gpx+xml, img/png; charset=utf-8"
    request.Headers.Add("Authorization", "xxxxMYKEYxxxx")
    request.Headers.Add("Content-Type", "application/json; charset=utf-8")

    Using writer = New System.IO.StreamWriter(request.GetRequestStream())
        Dim byteArray As Byte() = System.Text.Encoding.UTF8.GetBytes({"coordinates:[[8.681495,49.41461],[8.686507,49.41943],[8.687872,49.420318]]"})
        request.ContentLength = byteArray.Length
        writer.Write(byteArray)
        writer.Close()
    End Using
    Dim responseContent As String
    Using response = TryCast(request.GetResponse(), System.Net.HttpWebResponse)
        Using reader = New System.IO.StreamReader(response.GetResponseStream())
            responseContent = reader.ReadToEnd()
            Console.WriteLine(responseContent.ToString())
        End Using
    End Using
End Sub

例子表明请求体的内容应该是这样的:

{"coordinates":[[8.681495,49.41461],[8.686507,49.41943],[8.687872,49.420318]]}

但是当 运行 这个例子时,我得到以下错误:

'The remote server returned an error: (500) Internal Server Error.'

所以我认为请求失败是因为 Json 无效。 我的问题是如何创建一个 JSON 结果与上面提供的示例-JSON 相同?

API 需要一个 JSON 对象,表示双精度值数组的数组,作为 HttpRequest 的内容,编码为 UTF-8 字符串,作为字节数组发送.

此集合可以用 List(Of List(Of Double) 属性 .Net 类型表示 class:

' Note that JavaScriptSrializer might ignore <JsonProperty>,
' so use lower case, since the Web API is case-sensitive
Friend Class MyObject
    <JsonProperty("coordinates")>
    Public Property coordinates As List(Of List(Of Double))
End Class

在此之后,我们只需要填写列表:

Dim myobj = New MyObject() With {
    .Coordinates = New List(Of List(Of Double)) From {
        New List(Of Double)({8.681495, 49.41461}),
        New List(Of Double)({8.686507, 49.41943}),
        New List(Of Double)({8.687872, 49.420318})
    }
}

并使用 Json.Net (install the NuGet package via NuGet Package Manager) or JavaScriptSerializer(或任何其他可用的 JSON 序列化程序)对其进行序列化:

JavaScriptSerializer 需要项目引用 System.Web.Extension 并导入 System.Web.Script.Serialization.

' Using Json.Net
Dim Json As String = JsonConvert.SerializeObject(myobj)

' Or JavaScriptSerializer
Dim json = New JavaScriptSerializer().Serialize(myobj)

► 原代码不止一个问题:

  • webRequest.ContentLength设置太迟:需要在请求发送前设置
  • 用于写入 WebRequest Stream 的 StreamWriter 将危及进程:不需要它,它将在字节写入 Request Stream 之前关闭
  • Content-Type不能用Headers设置,必须用WebRequest.ContentType属性
  • 添加 SecurityProtocolType.Tls12 以防此代码用于 Windows 7 或 WM(在 Windows 7 中,默认为 SecurityProtocolType.Ssl3 Or SecurityProtocolType.Tls,因此 TLS1.0,实际上不再使用了,TLS1.2 是(仍然)此时的主要参与者)

修复原代码,使用JavaScriptSerializer序列化请求数据:

Imports System.Web.Script.Serialization替换为Imports Newtonsoft.Json如果你使用Json.Net.

Imports System.IO
Imports System.Text
Imports System.Web.Script.Serialization

Dim myobj = New MyObject() With {
    .Coordinates = New List(Of List(Of Double)) From {
        New List(Of Double)({8.681495, 49.41461}),
        New List(Of Double)({8.686507, 49.41943}),
        New List(Of Double)({8.687872, 49.420318})
    }
}

Dim json As String = New JavaScriptSerializer().Serialize(myobj)

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
Dim request = WebRequest.CreateHttp("https://api.openrouteservice.org/v2/directions/driving-car/gpx")

request.Method = "POST"
request.PreAuthenticate = True
request.Accept = "application/json, application/geo+json, application/gpx+xml, img/png; charset=utf-8"
request.Headers.Add("Authorization", "[Your API Key]")
request.ContentType = "application/json; charset=utf-8"

Dim jsonBytes = Encoding.UTF8.GetBytes(json)
request.ContentLength = jsonBytes.Length
Using reqStream = request.GetRequestStream()
    reqStream.Write(jsonBytes, 0, jsonBytes.Length)
End Using

Dim responseContent As String = String.Empty
Using response = DirectCast(request.GetResponse(), HttpWebResponse),
    responseStream = response.GetResponseStream(),
    reader = New StreamReader(responseStream)
    responseContent = reader.ReadToEnd()
End Using