Newtonsoft JSON parsing into object - json

My VB is a bit rusty but I need to parse a JSON string. I did it already in C# where I didn't have an issue. This is an old project and I'm using VS2008 for it.
This is my class:
Public Class ResponseMeta
Private _type As String
<JsonProperty("type")> _
Public Property type() As String
Get
Return _type.ToString()
End Get
Set(ByVal value As String)
_type = value
End Set
End Property
Private _message As String
<JsonProperty("message")> _
Public Property message() As String
Get
Return _message
End Get
Set(ByVal value As String)
_message = value
End Set
End Property
Private _message_v1 As String
<JsonProperty("message-v1")> _
Public Property message_v1() As String
Get
Return _message_v1
End Get
Set(ByVal value As String)
_message_v1 = value
End Set
End Property
Private _message_v2 As String
<JsonProperty("message-v2")> _
Public Property message_v2() As String
Get
Return _message_v2
End Get
Set(ByVal value As String)
_message_v2 = value
End Set
End Property
Private _message_v3 As String
<JsonProperty("message-v3")> _
Public Property message_v3() As String
Get
Return _message_v3
End Get
Set(ByVal value As String)
_message_v3 = value
End Set
End Property
Private _message_v4 As String
<JsonProperty("message-v4")> _
Public Property message_v4() As String
Get
Return _message_v4
End Get
Set(ByVal value As String)
_message_v4 = value
End Set
End Property
End Class
The code to deserialize is:
Dim test As String
test = "{""response-meta"":{""type"":""S"",""message"":"""",""Total No Of Records"":"""",""message-v1"":""1"",""message-v2"":"""",""message-v3"":"""",""message-v4"":""""}}"
Dim testcl As ResponseMeta
testcl = JsonConvert.DeserializeObject(Of ResponseMeta)(test)
All properties of the object are set to Nothing and if I add watch, it says:
type = {"Object reference not set to an instance of an object."}
I have now spent countless hours on this and Google doesn't found a hint or a clue of what might be getting wrong here.
Any suggestions are very welcome.

The JSON does not match up to what you are trying to parse it to.
You are missing a root object.
Public Class RootObject
Private _root As ResponseMeta
<JsonProperty("response-meta")> _
Public Property ResponseMeta() As ResponseMeta
Get
Return _root
End Get
Set(ByVal value As ResponseMeta)
_root = value
End Set
End Property
End Class
So based on the JSON you would need to deserialize to root object first then get the meta data
Dim root As RootObject = JsonConvert.DeserializeObject(Of RootObject)(test)
Dim testcl As ResponseMeta = root.ResponseMeta

Related

'The node must be of type 'JsonObject'.'

I'm trying to parse this Json
With the code:
Dim streamData As Stream = Nothing
Using http As New HttpClient
Dim url As String = "https://api.hotbit.io/api/v1/market.deals?market=KIBA/USDT&limit=150&last_id=1521100930&api_key=44812d8f-66d3-01c0-94c3b29305040b03&sign=98EEC3D69D3F70F9BDFED901984B2AA4"
Dim t As Task(Of Stream) = http.GetStreamAsync(url)
streamData = t.Result
End Using
Dim jsonResponse As JsonNode = JsonNode.Parse(streamData)
Dim result As JsonObject = jsonResponse("result").AsObject
Dim c As String = String.Empty
For Each kvp In result.AsEnumerable
c &= kvp.Value("price").ToString & vbCr
Next
RichTextBox1.Text = c
End Sub
but I keep getting the error at debug
The node must be of type 'JsonObject'.'
on the line
Dim result As JsonObject = jsonResponse("result").AsObject
How it comes it gives an error If I'm already trying to parse it as a Jsonobject?
Thanks
Give a go at this..
Paste this into a new class file:
Namespace HotBit
Partial Public Class TradeCollection
<JsonProperty("error")>
Public Property [Error] As Object
<JsonProperty("result")>
Public Property Result As List(Of Result)
<JsonProperty("id")>
Public Property Id As Long
End Class
Partial Public Class Result
<JsonProperty("id")>
Public Property Id As Long
<JsonProperty("time")>
Public Property Time As Long
<JsonProperty("price")>
Public Property Price As String
<JsonProperty("amount")>
<JsonConverter(GetType(ParseStringConverter))>
Public Property Amount As Long
<JsonProperty("type")>
Public Property Type As TypeEnum
End Class
Public Enum TypeEnum
Buy
Sell
End Enum
Partial Public Class TradeCollection
Public Shared Function FromJson(ByVal json As String) As TradeCollection
Return JsonConvert.DeserializeObject(Of TradeCollection)(json, Settings)
End Function
End Class
Public Module Serialize
<Extension()>
Public Function ToJson(ByVal self As TradeCollection) As String
Return JsonConvert.SerializeObject(self, Settings)
End Function
End Module
Friend Module Converter
Public ReadOnly Settings As JsonSerializerSettings = New JsonSerializerSettings With {
.MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
.DateParseHandling = DateParseHandling.None
}
End Module
Friend Class ParseStringConverter
Inherits JsonConverter
Public Overrides Function CanConvert(ByVal t As Type) As Boolean
Return t Is GetType(Long) OrElse t Is GetType(Long?)
End Function
Public Overrides Function ReadJson(ByVal reader As JsonReader, ByVal t As Type, ByVal existingValue As Object, ByVal serializer As JsonSerializer) As Object
If reader.TokenType = JsonToken.Null Then Return Nothing
Dim value = serializer.Deserialize(Of String)(reader)
Dim l As Long
If Long.TryParse(value, l) Then
Return l
End If
Throw New Exception("Cannot unmarshal type long")
End Function
Public Overrides Sub WriteJson(ByVal writer As JsonWriter, ByVal untypedValue As Object, ByVal serializer As JsonSerializer)
If untypedValue Is Nothing Then
serializer.Serialize(writer, Nothing)
Return
End If
Dim value = CLng(untypedValue)
serializer.Serialize(writer, value.ToString())
Return
End Sub
Public Shared ReadOnly Singleton As ParseStringConverter = New ParseStringConverter()
End Class
Friend Class TypeEnumConverter
Inherits JsonConverter
Public Overrides Function CanConvert(ByVal t As Type) As Boolean
Return t Is GetType(TypeEnum) OrElse t Is GetType(TypeEnum?)
End Function
Public Overrides Function ReadJson(ByVal reader As JsonReader, ByVal t As Type, ByVal existingValue As Object, ByVal serializer As JsonSerializer) As Object
If reader.TokenType = JsonToken.Null Then Return Nothing
Dim value = serializer.Deserialize(Of String)(reader)
Select Case value
Case "buy"
Return TypeEnum.Buy
Case "sell"
Return TypeEnum.Sell
End Select
Throw New Exception("Cannot unmarshal type TypeEnum")
End Function
Public Overrides Sub WriteJson(ByVal writer As JsonWriter, ByVal untypedValue As Object, ByVal serializer As JsonSerializer)
If untypedValue Is Nothing Then
serializer.Serialize(writer, Nothing)
Return
End If
Dim value = CType(untypedValue, TypeEnum)
Select Case value
Case TypeEnum.Buy
serializer.Serialize(writer, "buy")
Return
Case TypeEnum.Sell
serializer.Serialize(writer, "sell")
Return
End Select
Throw New Exception("Cannot marshal type TypeEnum")
End Sub
Public Shared ReadOnly Singleton As TypeEnumConverter = New TypeEnumConverter()
End Class
End Namespace
Then install Newtonsoft (if not already) and Imports it
Then Imports HotBit (or if you changed the Namespace of the "paste this" above, Imports that new namespace
Then do your request and query the result e.g.:
Sub Main(args As String())
Dim s = New WebClient().DownloadString("https://api.hotbit.io/api/v1/market.deals?market=KIBA/USDT&limit=150&last_id=1521100930&api_key=44812d8f-66d3-01c0-94c3b29305040b03&sign=98EEC3D69D3F70F9BDFED901984B2AA4")
Dim tc = TradeCollection.FromJson(s)
Dim prices = String.Join(","c, tc.Result.Select(Function(r) r.Price))
End Sub

How does one get the values from the inner classes of deserialized JSON?

I am trying to get the lat and lng values from the Google Geocode API. I set up the classes using a vb translation of parse google maps geocode json response to object using Json.Net. I can access the status, and the top level result, but I cannot seem to access the children of result, even though the data shows up in debug mode when I hover over result and open up the plus signs.
How does one get the values from the inner classes of deserialized json?
Lines setting decLat and decLon say "geometry is not a member of Systems.Array"
Dim result = New System.Net.WebClient().DownloadString(Request.ToString)
Response = JsonConvert.DeserializeObject(Of GoogleGeoCodeResponse)(result)
If Response.status = "OK" Then
decLat = Response.results.geometry.location.lat
decLon = Response.results.geometry.location.lng
Public Class GoogleGeoCodeResponse
Public Property status() As String
Get
Return m_status
End Get
Set(value As String)
m_status = Value
End Set
End Property
Private m_status As String
Public Property results() As results()
Get
Return m_results
End Get
Set(value As results())
m_results = Value
End Set
End Property
Private m_results As results()
End Class
Public Class results
Public Property formatted_address() As String
Get
Return m_formatted_address
End Get
Set(value As String)
m_formatted_address = Value
End Set
End Property
Private m_formatted_address As String
Public Property geometry() As Geometry
Get
Return m_geometry
End Get
Set(value As Geometry)
m_geometry = Value
End Set
End Property
Private m_geometry As Geometry
Public Property types() As String()
Get
Return m_types
End Get
Set(value As String())
m_types = Value
End Set
End Property
Private m_types As String()
Public Property address_components() As address_component()
Get
Return m_address_components
End Get
Set(value As address_component())
m_address_components = Value
End Set
End Property
Private m_address_components As address_component()
End Class
Public Class geometry
Public Property location_type() As String
Get
Return m_location_type
End Get
Set(value As String)
m_location_type = Value
End Set
End Property
Private m_location_type As String
Public Property location() As location
Get
Return m_location
End Get
Set(value As location)
m_location = Value
End Set
End Property
Private m_location As location
End Class
Public Class location
Public Property lat() As Decimal
Get
Return m_lat
End Get
Set(value As Decimal)
m_lat = value
End Set
End Property
Private m_lat As String
Public Property lng() As Decimal
Get
Return m_lng
End Get
Set(value As Decimal)
m_lng = value
End Set
End Property
Private m_lng As String
End Class
Public Class address_component
Public Property long_name() As String
Get
Return m_long_name
End Get
Set(value As String)
m_long_name = Value
End Set
End Property
Private m_long_name As String
Public Property short_name() As String
Get
Return m_short_name
End Get
Set(value As String)
m_short_name = Value
End Set
End Property
Private m_short_name As String
Public Property types() As String()
Get
Return m_types
End Get
Set(value As String())
m_types = Value
End Set
End Property
Private m_types As String()
End Class

How to return two objects (including one list) in JSON with WCF

I am trying to resolve my issue.
This is my Service Contract (IService1.vb)
<OperationContract()> _
<WebInvoke(Method:="GET", BodyStyle:=WebMessageBodyStyle.Wrapped, ResponseFormat:=WebMessageFormat.Json, UriTemplate:="/GetBooks")> _
Function GetBooks() As List(Of Book)
<DataContract()> _
Class Book
Public Property bookchapter() As List(Of Chapter)
Get
Return m_bookchapter
End Get
Set(value As List(Of Chapter))
m_bookchapter = value
End Set
End Property
Private m_bookchapter As List(Of Chapter)
Public Property success() As Integer
Get
Return m_success
End Get
Set(value As Integer)
m_success = value
End Set
End Property
Private m_success As Integer
End Class
<DataContract()> _
Class Chapter
Public Property description() As String
Get
Return m_description
End Get
Set(value As String)
m_description = value
End Set
End Property
Private m_description As String
End Class
This is my Service (Service1.vb)
Public Function GetBooks() As List(Of IGPService.Book) Implements IGPService.GetBooks
Dim books As New List(Of IGPService.Book)
Dim newBook As IGPService.Book = New IGPService.Book
For i As Integer = 0 To 3
Dim newchapter As IGPService.Chapter = New IGPService.Chapter
newchapter.description = "Chapter1"
newBook.bookchapter.Add(newchapter)
Next
newBook.success = 1
books.Add(newBook)
Return books
End Function
When I call GetBooks, I get the following error:
The server encountered an error processing the request. See server
logs for more details.
I don't know what is wrong here. I couldn't find anything in the Windows EventLog.
I added a New() Contructor to the Book Class and now it works. But i don't know why!
Class Book
Public Property bookchapter() As List(Of Chapter)
Get
Return m_bookchapter
End Get
Set(value As List(Of Chapter))
m_bookchapter = value
End Set
End Property
Private m_bookchapter As List(Of Chapter)
Public Property success() As Integer
Get
Return m_success
End Get
Set(value As Integer)
m_success = value
End Set
End Property
Private m_success As Integer
**Public Sub New()
bookchapter = New List(Of Chapter)
End Sub**
End Class
I want to understand why this is. Can somebody explain me the difference with and without New()!

DataContractJsonSerializer include object name in JSON object

I'm trying to serialize a JSON object so I can send it to a web service. I'm using this asp.net vb code:
Dim ser As DataContractJsonSerializer = New DataContractJsonSerializer(postData.GetType())
Dim MS As MemoryStream = New MemoryStream()
ser.WriteObject(MS, postData)
json = Encoding.UTF8.GetString(MS.ToArray())
which produces this JSON:
{"guid":"10049cf5-a622-4aa6-a1d5-58022c4e2a19"}
But what I NEED...is this JSON:
{"registerRequest": {"guid":"10049cf5-a622-4aa6-a1d5-58022c4e2a19"}}
here is the class definition for the object I'm trying to send:
Partial Public Class registerRequest
Private Property _guid As String
Public Property guid As String
Get
Return _guid
End Get
Set(value As String)
_guid = value
End Set
End Property
Sub New()
End Sub
End Class
How do I get the name of the class to appear in the JSON object as described above?
Add datacontractjsonserializersettings to your constructor on DataContractDataSerializer
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.json.datacontractjsonserializersettings.emittypeinformation.aspx
Try using rootname setting in the constructor instead.
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.json.datacontractjsonserializersettings.rootname.aspx
OK, to match the format I Just created a wrapper class with a "registerRequest" object inside of it. Kind of a work around, but it works!
Partial Public Class SerializedRegisterRequest
Private Property _registerRequest As registerRequest
Public Property registerRequest As registerRequest
Get
Return _registerRequest
End Get
Set(value As registerRequest)
_registerRequest = value
End Set
End Property
Sub New()
End Sub
End Class
Partial Public Class registerRequest
Private Property _guid As String
Public Property guid As String
Get
Return _guid
End Get
Set(value As String)
_guid = value
End Set
End Property
Sub New()
End Sub
End Class

JSON deserialize in vb.net code behind

I am a java developer and I am working on .net first time. I have used JSON with YUI, but this is first time I am using JQUERY. I have converted Java script object to JSON string using JSON.stringify() and I am getting the same JSON string in code behind, but when I tried to deserialize to the .net object, I am getting the value for property which is Integer, but I not getting the value for String object.
// Client Side
$("#ButtonSave").click(function () {
//convert gridview to JSON
var jsonData = new Array();
$.map($("table[id*=Gridview1] tr"), function (item, index) {
if ($(item).find("input[type=text]").length > 0) {
jsonData[index] = new Object();
jsonData[index].charge = $(item).find("input[type=text][id*=txtCharge]").val();
jsonData[index].produce = $(item).find("input[type=text][id*=txtProduce]").val();
jsonData[index].weight = $(item).find("input[type=text][id*=txtWeight]").val();
jsonData[index].feet = $(item).find("input[type=text][id*=txtFeet]").val();
jsonData[index].orderNumber = $(item).find("input[type=text][id*=txtOrderNumber]").val();
jsonData[index].comments = $(item).find("input[type=text][id*=txtComments]").val();
}
});
var jsonStringData = JSON.stringify(jsonData);
var jqxhr = $.ajax({
url: "Correction.aspx",
type: "POST",
timeout: 10000,
data: "jsonData=" + jsonStringData
})
.error(function () {
alert('Error');
})
.success(function (data) {
alert('Success');
});
});
//Code Behind
If Request.Form("jsonData") IsNot Nothing Then
Dim cita As New TurnDetailVO
Dim ser As New JavaScriptSerializer()
Dim items As List(Of TurnDetailVO) = ser.Deserialize(Of List(Of TurnDetailVO))(Request.Form("jsonData"))
items.RemoveAt(0)
For Each cita In items
Console.WriteLine(cita.CHARGE_ID, cita.PROD_ID)
Next
End If
// Value Object
Imports Microsoft.VisualBasic
Imports System.Runtime.Serialization
Public Class TurnDetailVO
Private _CHARGE As String
Private _PROD As String
Private _WEIGHT As Integer
Private _FEET As Integer
Private _ORDER_NUMBER As String
Private _COMMENTS As String
Public Sub New()
_CHARGE = " "
_PROD = " "
_WEIGHT = 0
_FEET = 0
_ORDER_NUMBER = " "
_COMMENTS = " "
End Sub
Public Property CHARGE() As String
Get
Return _CHARGE
End Get
Set(ByVal value As String)
_CHARGE = value
End Set
End Property
Public Property PROD() As String
Get
Return _PROD
End Get
Set(ByVal value As String)
_PROD = value
End Set
End Property
Public Property WEIGHT() As Integer
Get
Return _WEIGHT
End Get
Set(ByVal value As Integer)
_WEIGHT = value
End Set
End Property
Public Property FEET() As Integer
Get
Return _FEET
End Get
Set(ByVal value As Integer)
_FEET = value
End Set
End Property
Public Property ORDER_NUMBER() As String
Get
Return _ORDER_NUMBER
End Get
Set(ByVal value As String)
_ORDER_NUMBER = value
End Set
End Property
Public Property COMMENTS() As String
Get
Return _COMMENTS
End Get
Set(ByVal value As String)
_COMMENTS = value
End Set
End Property
Public Function Clone() As TurnDetailVO
Return DirectCast(Me.MemberwiseClone(), TurnDetailVO)
End Function
End Class
// JSON String
"[null,
{"charge":"T860243","produce":"S877020","weight":"13188","feet":"2898","orderNumber":"AN46270","comments":""},
{"charge":"T860243","produce":"S877021","weight":"13538","feet":"2978","orderNumber":"AN46270","comments":""},
{"charge":"T860243","produce":"S877022","weight":"30118","feet":"6618","orderNumber":"AN46270","comments":""},
{"charge":"T860243","produce":"S877023","weight":"23455","feet":"3345","orderNumber":"AN46270","comments":""}]"
It looks like the deserializtion isn't behaving as expected due to two of your field names being different.
If I changed the property names PROD to PRODUCE and ORDER_NUMBER to ORDERNUMBER I could get it working. Note that you can leave the private field names as they are, it is just the property names that need to change.