Object is nothing after json deserialization - json

I want to deserialize a json file into 'Artikelstammdaten' and afterwards to a list of 'Artikelstammdaten' (don't know how to iterate over the deserialized json yet). I already tried to deserialize it into the Rootobject, but the object was also "Nothing"Here is what i have tried:
If OpenfilePath IsNot Nothing Then
Dim asd As Artikelstammdaten
Dim fileReader As StreamReader
fileReader = My.Computer.FileSystem.OpenTextFileReader(OpenfilePath)
asd = JsonConvert.DeserializeObject(Of Artikelstammdaten)(fileReader.ReadToEnd)
End If
Edit: This is what the class structure looks like now:
Public Class Artikelstammdaten
Public Property Artikel As String
Public Property BezeichnungDE As String
Public Property BezeichnungEN As String
Public Property Einheit As String
Public Property MatGrp As String
Public Property Kostenart As Integer?
Public Property Vertriebstext_DE As String
Public Property Vertriebstext_EN As String
Public Property Stueckliste As String
Public Property Status As String
Public Property Klasse As String
Public Property Mantelflaeche As Double?
Public Property Gewicht As Integer?
Public Property KlasseID As String
End Class
Public Class Stueckliste
Public Property Verkaufsartikel As String
Public Property Position As Integer?
Public Property PosArtikel As String
Public Property PosBezeichnung As String
Public Property PosKostenart As Integer?
Public Property Datum As String
Public Property Material As Double?
Public Property GMK As Double?
Public Property Lohn As Double?
Public Property Menge As Integer?
Public Property Mengeneinheit As String
End Class
Public Class Arbeitsgaenge
Public Property Verkaufsartikel As String
Public Property AGNR As Integer?
Public Property Bereich As String
Public Property Lohn As Double?
Public Property Kostenstelle As Integer?
Public Property ARBPLATZ As String
End Class
Public Class RootObject
Public Property Artikelstammdaten As List(Of Artikelstammdaten)
Public Property Stueckliste As List(Of Stueckliste)
Public Property Arbeitsgaenge As List(Of Arbeitsgaenge)
End Class
Edit: I also changed the names from "ManufacturingCosts" and "MaterialCosts" to "Stueckliste" and "Arbeitsgaenge"
And here is my json-File:
{"Artikelstammdaten":[{"Artikel":"VAUBEF0010"},
{"BezeichnungDE":"Sammelbandantrieb"},
{"BezeichnungEN":"Collection belt drive N50"},
{"Einheit":"STK"},
{"MatGrp":"VAU"},
{"Kostenart": 1500},
{"Vertriebstext_DE": "Antrieb, Umlenkungen"},
{"Vertriebstext_EN": "Drive, Deflections"},
{"Stueckliste":"VAUBEF0010"},
{"Status":"F"},
{"Klasse":"VTPIMV"},
{"Mantelflaeche":1.3},
{"Gewicht":120},
{"KlasseID":"1.2.6.5"}],
"Stueckliste": [{"Verkaufsartikel":"VAUBEF0010"},
{"Position": 10},
{"PosArtikel":"Z0306251"},
{"PosBezeichnung":"VEL Elektro- Montagematerial"},
{"PosKostenart":9105},
{"Datum":"2022-01-31"},
{"Material":60.41},
{"GMK":3.63},
{"Lohn":2.07},
{"Menge":1},
{"Mengeneinheit":"STK"}],
"Arbeitsgaenge": [{"Verkaufsartikel":"VAUBEF0010"},
{"AGNR":10},
{"Bereich":"Mechanische Montage"},
{"Lohn":89.1},
{"Kostenstelle":523500},{"ARBPLATZ":"K950M"}]
}
What am i doing wrong?

I tried DeserializeObject with the json you provided
Public Class Artikelstammdaten
Public Property Artikel As String
Public Property BezeichnungDE As String
Public Property BezeichnungEN As String
Public Property Einheit As String
Public Property MatGrp As String
Public Property Kostenart As Integer
Public Property Vertriebstext_DE As String
Public Property Vertriebstext_EN As String
Public Property Stueckliste As String
Public Property Status As String
Public Property Klasse As String
Public Property Mantelflaeche As Double
Public Property Gewicht As Integer
Public Property KlasseID As String
End Class
Public Class ManufacturingCost
Public Property Verkaufsartikel As String
Public Property Position As Integer
Public Property PosArtikel As String
Public Property PosBezeichnung As String
Public Property PosKostenart As Integer
Public Property Datum As String
Public Property Material As Double
Public Property GMK As Double
Public Property Lohn As Double
Public Property Menge As Integer
Public Property Mengeneinheit As String
End Class
Public Class MaterialCost
Public Property Verkaufsartikel As String
Public Property AGNR As Integer
Public Property Bereich As String
Public Property Lohn As Double
Public Property Kostenstelle As Integer
Public Property ARBPLATZ As String
End Class
Public Class Root4
Public Property Artikelstammdaten As List(Of Artikelstammdaten)
Public Property ManufacturingCosts As List(Of ManufacturingCost)
Public Property MaterialCosts As List(Of MaterialCost)
End Class
Private Sub btnJson4_Click(sender As Object, e As EventArgs)
Dim Json As String = "{'Artikelstammdaten':[{'Artikel':'VAUBEF0010'},
{'BezeichnungDE':'Sammelbandantrieb'},
{'BezeichnungEN':'Collection belt drive N50'},
{'Einheit':'STK'},
{'MatGrp':'VAU'},
{'Kostenart': 1500},
{'Vertriebstext_DE': 'Antrieb, Umlenkungen'},
{'Vertriebstext_EN': 'Drive, Deflections'},
{'Stueckliste':'VAUBEF0010'},
{'Status':'F'},
{'Klasse':'VTPIMV'},
{'Mantelflaeche':1.3},
{'Gewicht':120},
{'KlasseID':'1.2.6.5'}],
'ManufacturingCosts': [{'Verkaufsartikel':'VAUBEF0010'},
{'Position': 10},
{'PosArtikel':'Z0306251'},
{'PosBezeichnung':'VEL Elektro- Montagematerial'},
{'PosKostenart':9105},
{'Datum':'2022-01-31'},
{'Material':60.41},
{'GMK':3.63},
{'Lohn':2.07},
{'Menge':1},
{'Mengeneinheit':'STK'}],
'MaterialCosts': [{'Verkaufsartikel':'VAUBEF0010'},
{'AGNR':10},
{'Bereich':'Mechanische Montage'},
{'Lohn':89.1},
{'Kostenstelle':523500},{'ARBPLATZ':'K950M'}]}"
Dim rt4 As New Root4
rt4 = JsonConvert.DeserializeObject(Of Root4)(Json)
Console.WriteLine(rt4.Artikelstammdaten(0).Artikel)
Console.WriteLine(rt4.Artikelstammdaten(1).BezeichnungDE)
End Sub
The json structure you provided and the clss you created are different.

Your problem is that your the values for the JSON properties "Artikelstammdaten", "Stueckliste" and "Arbeitsgaenge" are not objects. They are arrays of single-property objects. This can be seen if you reformat your JSON with e.g. https://jsonlint.com/:
{
"Artikelstammdaten": [{
"Artikel": "VAUBEF0010"
},
{
"BezeichnungDE": "Sammelbandantrieb"
},
{
"BezeichnungEN": "Collection belt drive N50"
},
{
"Einheit": "STK"
},
{
"MatGrp": "VAU"
},
{
"Kostenart": 1500
},
{
"Vertriebstext_DE": "Antrieb, Umlenkungen"
},
{
"Vertriebstext_EN": "Drive, Deflections"
},
{
"Stueckliste": "VAUBEF0010"
},
{
"Status": "F"
},
{
"Klasse": "VTPIMV"
},
{
"Mantelflaeche": 1.3
},
{
"Gewicht": 120
},
{
"KlasseID": "1.2.6.5"
}
],
"Stueckliste": [{
"Verkaufsartikel": "VAUBEF0010"
},
{
"Position": 10
},
{
"PosArtikel": "Z0306251"
},
{
"PosBezeichnung": "VEL Elektro- Montagematerial"
},
{
"PosKostenart": 9105
},
{
"Datum": "2022-01-31"
},
{
"Material": 60.41
},
{
"GMK": 3.63
},
{
"Lohn": 2.07
},
{
"Menge": 1
},
{
"Mengeneinheit": "STK"
}
],
"Arbeitsgaenge": [{
"Verkaufsartikel": "VAUBEF0010"
},
{
"AGNR": 10
},
{
"Bereich": "Mechanische Montage"
},
{
"Lohn": 89.1
},
{
"Kostenstelle": 523500
}, {
"ARBPLATZ": "K950M"
}
]
}
You would like to deserialize those arrays of single-property objects into c# models where each nested JSON property is bound to a model property. Since this is not implemented out of the box by Json.NET, you will need to create a custom generic JsonConverter such as the following:
Public Class ObjectToDictionaryArrayConverter(Of T)
Inherits JsonConverter
Public Overrides Function CanConvert(ByVal objectType As Type) As Boolean
Return objectType Is GetType(T)
End Function
Public Overrides ReadOnly Property CanWrite As Boolean
Get
Return False
End Get
End Property
Public Overrides Function ReadJson(ByVal reader As JsonReader, ByVal objectType As Type, ByVal existingValue As Object, ByVal serializer As JsonSerializer) As Object
If existingValue Is Nothing Then
Dim contract = serializer.ContractResolver.ResolveContract(objectType)
existingValue = contract.DefaultCreator()()
End If
Select Case JsonExtensions.MoveToContentAndAssert(reader).TokenType
Case JsonToken.StartArray
While JsonExtensions.ReadToContentAndAssert(reader).TokenType <> JsonToken.EndArray
Select Case reader.TokenType
Case JsonToken.StartObject
serializer.Populate(reader, existingValue)
Case Else
Throw New JsonSerializationException("Unexpected token type " & reader.TokenType.ToString())
End Select
End While
Case JsonToken.StartObject
serializer.Populate(reader, existingValue)
Case Else
Throw New JsonSerializationException("Unexpected token type " & reader.TokenType.ToString())
End Select
Return existingValue
End Function
Public Overrides Sub WriteJson(ByVal writer As JsonWriter, ByVal value As Object, ByVal serializer As JsonSerializer)
Throw New NotImplementedException()
End Sub
End Class
Public Module JsonExtensions
<System.Runtime.CompilerServices.Extension()>
Public Function ReadToContentAndAssert(ByVal reader As JsonReader) As JsonReader
Return JsonExtensions.ReadAndAssert(reader).MoveToContentAndAssert()
End Function
<System.Runtime.CompilerServices.Extension()>
Public Function MoveToContentAndAssert(ByVal reader As JsonReader) As JsonReader
If reader Is Nothing Then Throw New ArgumentNullException()
If reader.TokenType = JsonToken.None Then reader.ReadAndAssert() ' Skip past beginning of stream.
While reader.TokenType = JsonToken.Comment ' Skip past comments.
reader.ReadAndAssert()
End While
Return reader
End Function
<System.Runtime.CompilerServices.Extension()>
Public Function ReadAndAssert(ByVal reader As JsonReader) As JsonReader
If reader Is Nothing Then Throw New ArgumentNullException()
If Not reader.Read() Then Throw New JsonReaderException("Unexpected end of JSON stream.")
Return reader
End Function
End Module
Then modify your RootObject as follows, to replace the lists with single objects:
Public Class RootObject
Public Property Artikelstammdaten As Artikelstammdaten
Public Property Stueckliste As Stueckliste
Public Property Arbeitsgaenge As Arbeitsgaenge
End Class
And deserialize as follows:
Dim root as RootObject = Nothing
If OpenfilePath IsNot Nothing Then
Dim settings = New JsonSerializerSettings() With { .Converters = New JsonConverter() { _
New ObjectToDictionaryArrayConverter(Of Artikelstammdaten)(), _
New ObjectToDictionaryArrayConverter(Of Stueckliste)(), _
New ObjectToDictionaryArrayConverter(Of Arbeitsgaenge)() } }
Using fileReader = New StreamReader(OpenfilePath)
Using jsonReader = New JsonTextReader(fileReader)
root = JsonSerializer.CreateDefault(settings).Deserialize(Of RootObject)(jsonReader)
End Using
End Using
End If
Demo vb.net fiddle here.
Notes:
If you can modify your JSON format so that "Artikelstammdaten", "Stueckliste" and "Arbeitsgaenge" are objects rather than arrays of objects, the converter becomes unnecessary.
For performance reasons, Newtonsoft recommends reading directly from a file using a stream reader.
a StreamReader should always be closed via a Using statement after you are done reading from it.
I did not implement re-serialization of an object as an array of single-property objects because your question did not indicate it was necessary.
In c# ObjectToDictionaryArrayConverter<T> would be as follows:
public class ObjectToDictionaryArrayConverter<T> : JsonConverter
{
public override bool CanConvert(Type objectType) => objectType == typeof(T);
public override bool CanWrite => false;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (existingValue == null)
{
var contract = serializer.ContractResolver.ResolveContract(objectType);
existingValue = contract.DefaultCreator();
}
switch (reader.MoveToContentAndAssert().TokenType)
{
case JsonToken.StartArray:
{
while (reader.ReadToContentAndAssert().TokenType != JsonToken.EndArray)
{
switch (reader.TokenType)
{
case JsonToken.StartObject:
serializer.Populate(reader, existingValue);
break;
default:
throw new JsonSerializationException("Unexpected token type " + reader.TokenType.ToString());
}
}
}
break;
case JsonToken.StartObject:
serializer.Populate(reader, existingValue);
break;
default:
throw new JsonSerializationException("Unexpected token type " + reader.TokenType.ToString());
}
return existingValue;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) => throw new NotImplementedException();
}
public static partial class JsonExtensions
{
public static JsonReader ReadToContentAndAssert(this JsonReader reader) =>
reader.ReadAndAssert().MoveToContentAndAssert();
public static JsonReader MoveToContentAndAssert(this JsonReader reader)
{
if (reader == null)
throw new ArgumentNullException();
if (reader.TokenType == JsonToken.None) // Skip past beginning of stream.
reader.ReadAndAssert();
while (reader.TokenType == JsonToken.Comment) // Skip past comments.
reader.ReadAndAssert();
return reader;
}
public static JsonReader ReadAndAssert(this JsonReader reader)
{
if (reader == null)
throw new ArgumentNullException();
if (!reader.Read())
throw new JsonReaderException("Unexpected end of JSON stream.");
return reader;
}
}
c# demo fiddle here.

Related

how can I parse the google books api and access the class properties (vb.net)

I'm trying to access Googles book api and just populate textboxes with the information.
Here's an example of the API json: [https://www.googleapis.com/books/v1/volumes?q=isbn:9780979799006]
I used Visual Studio's Paste Special to create the Class. Here it is:
Public Class GoogleBookData
Public Class Rootobject
Public Property kind As String
Public Property totalItems As Integer
Public Property items() As Item
End Class
Public Class Item
Public Property kind As String
Public Property id As String
Public Property etag As String
Public Property selfLink As String
Public Property volumeInfo As Volumeinfo
Public Property saleInfo As Saleinfo
Public Property accessInfo As Accessinfo
Public Property searchInfo As Searchinfo
End Class
Public Class Volumeinfo
Public Property title As String
Public Property subtitle As String
Public Property publishedDate As String
Public Property description As String
Public Property industryIdentifiers() As Industryidentifier
Public Property readingModes As Readingmodes
Public Property pageCount As Integer
Public Property printType As String
Public Property categories() As String
Public Property maturityRating As String
Public Property allowAnonLogging As Boolean
Public Property contentVersion As String
Public Property panelizationSummary As Panelizationsummary
Public Property imageLinks As Imagelinks
Public Property language As String
Public Property previewLink As String
Public Property infoLink As String
Public Property canonicalVolumeLink As String
End Class
Public Class Readingmodes
Public Property text As Boolean
Public Property image As Boolean
End Class
Public Class Panelizationsummary
Public Property containsEpubBubbles As Boolean
Public Property containsImageBubbles As Boolean
End Class
Public Class Imagelinks
Public Property smallThumbnail As String
Public Property thumbnail As String
End Class
Public Class Industryidentifier
Public Property type As String
Public Property identifier As String
End Class
Public Class Saleinfo
Public Property country As String
Public Property saleability As String
Public Property isEbook As Boolean
End Class
Public Class Accessinfo
Public Property country As String
Public Property viewability As String
Public Property embeddable As Boolean
Public Property publicDomain As Boolean
Public Property textToSpeechPermission As String
Public Property epub As Epub
Public Property pdf As Pdf
Public Property webReaderLink As String
Public Property accessViewStatus As String
Public Property quoteSharingAllowed As Boolean
End Class
Public Class Epub
Public Property isAvailable As Boolean
End Class
Public Class Pdf
Public Property isAvailable As Boolean
End Class
Public Class Searchinfo
Public Property textSnippet As String
End Class
End Class
I call this function to read the stream and get the Class data:
Public Shared Function getGoogleBookData(ByVal sSku As String) As GoogleBookData
Dim result As String = Nothing
Dim url As String = "https://www.googleapis.com/books/v1/volumes?q=isbn:"
url &= sSku
Dim request As HttpWebRequest = WebRequest.Create(url)
Dim response As HttpWebResponse = Nothing
Dim reader As StreamReader = Nothing
Dim myJson As String = Nothing
response = DirectCast(request.GetResponse(), HttpWebResponse)
reader = New StreamReader(response.GetResponseStream())
myJson = reader.ReadToEnd
Dim serializer As New System.Web.Script.Serialization.JavaScriptSerializer()
Dim myGBookData As New GoogleBookData
myGBookData = serializer.Deserialize(Of GoogleBookData)(myJson)
Return myGBookData
End Function
I call the function:
Dim gsSearchSku as String = "9780979799006"
Dim myGItem As New GoogleBookData
myGItem = getGoogleBookData(gsSearchSku)
Then, I've tried several things to try to access any data in the Class:
I know this doesn't work but put it here so you can get an idea of what I'm trying.
Dim sTitle as String = myGItem.Item.Title
I can't even run it. GoogleBookData.item is a class type and cannot be used as an expression.
No idea where to go from here.
Any help would be greatly appreciated!!

Dynamic JSON Deserialization with VB.NET [duplicate]

This question already has answers here:
Deserializing JSON when sometimes array and sometimes object
(7 answers)
Closed 2 years ago.
I get an API response in JSON in following format
{
"stuffs": {
"prop1": "abcd",
"prop2": "efgh",
"prop3": [
{
"content": "123456",
"name": "abc def",
"id": "123"
},
{
"content": "789012",
"name": "def ghi",
"id": "456"
}
]
}
}
I have created my Class to deserialize this object as below
Public Class Prop3
Public Property content As String
Public Property name As String
Public Property id As String
End Class
Public Class Stuffs
Public Property prop1 As String
Public Property prop2 As String
Public Property prop3 As Prop3()
End Class
Public Class Example
Public Property stuffs As Stuffs
End Class
Now the issue is, sometime, the response is not an array for prop3 and looks like this
{
"stuffs": {
"prop1": "abcd",
"prop2": "efgh",
"prop3": {
"content": "123456",
"name": "abc def",
"id": "123"
}
}
}
This time I get error while deserializing as the prop3 is not array anymore bu the property declared inside my class stuffs is expecting an array of property prop3.
Is there any dynamic way to resolve this? Like if the JSON response is an array it will be treated as array
Public Property prop3 As Prop3()
and in case it is not an array then it will treated as single property
Public Property prop3 As Prop3
Please suggest how to overcome this as changing the response from the API is not feasible because it is being developed by client and I need to use it my application, so I need to find some dynamic way to resolve this.
After suggestion made by Craig, I have tried in the below way, but still it is not happening, please suggest if I am making any mistake.
Public Class SingleValueArrayConverter(Of T)
Inherits JsonConverter
Public Overrides Sub WriteJson(ByVal writer As JsonWriter, ByVal value As Object, ByVal serializer As JsonSerializer)
serializer.Serialize(writer, value)
End Sub
Public Overrides Function ReadJson(ByVal reader As JsonReader, ByVal objectType As Type, ByVal existingValue As Object, ByVal serializer As JsonSerializer) As Object
Dim retVal As Object = New Object()
If reader.TokenType = JsonToken.StartObject Then
Dim instance As T = CType(serializer.Deserialize(reader, GetType(T)), T)
retVal = New List(Of T)() From {
instance
}
ElseIf reader.TokenType = JsonToken.StartArray Then
retVal = serializer.Deserialize(reader, objectType)
End If
Return retVal
End Function
Public Overrides Function CanConvert(ByVal objectType As Type) As Boolean
Return True
End Function
End Class
Public Class myClass1
Public Class Prop3
Public Property content As String
Public Property name As String
Public Property id As String
End Class
Public Class Stuffs
Public Property prop1 As String
Public Property prop2 As String
<JsonProperty("prop3")>
<JsonConverter(GetType(SingleValueArrayConverter(Of Prop3)))>
Public Property prop3 As Prop3()
End Class
Public Class Example
Public Property stuffs As Stuffs
End Class
End Class
It gives error:
Unable to cast object of type 'SingleValueArrayConverter`1[myClass1.myClass+Prop3]' to type 'Newtonsoft.Json.JsonConverter'.'
Any highlight on what I am missing please.
It worked after changing
Public Property prop3 As Prop3()
to
Public Property prop3 As List(Of Prop3)

Convert JSON object and array to same class in VB.net

I am trying to convert a JSON returned from a third party API, into VB.NET class object. The problem is that the JSON sometimes returns a node as an Array of objects and sometimes the same node as an single Object. So, while trying to convert when it receives Array of objects, the code throws exception.
{
"correlation_id": "228.9219622269229",
"Error": {
"messages": [
{
"code": "401",
"description": "Unauthorized"
}
]
},
"transaction_status": "Not Processed"
}
As you can see, there is an array of Error messages under Error->messages node. But sometimes, the JSON returned is simpy and object of Error messages something like
{
"correlation_id": "228.9219622269229",
"Error": {
"messages": {
"code": "401",
"description": "Unauthorized"
}
},
"transaction_status": "Not Processed"
}
I try to deserialize this JSON to the following class
Public Class PayeezyRefundResponse
Public correlation_id As String
Public transaction_status As String
Public validation_status As String
Public transaction_type As String
Public transaction_id As String
Public transaction_tag As String
Public bank_resp_code As String
Public bank_message As String
Public [Error] As PayeezyError
End Class
Public Class PayeezyError
Public messages As PayeezyErrorMessages()
End Class
Public Class PayeezyErrorMessages
Public code As String
Public description As String
End Class
But when the JSON returns Error message as single object, the code throws exception on PayeezyError class. How can I convert the JSON to this class so that it works in both the cases (i.e. with Array of objects and with single Object) ?
You can build a custom converter that can handle both cases as a List(Of PayeezyErrorMessage).
This converter always returns a List(Of PayeezyErrorMessage), even when the JSON contains a single object.
Note: in code, PayeezyErrorMessages, plural, has been renamed to PayeezyErrorMessage, single, since this class generates a single object.
The custom converter is added to the property as an attribute:
<JsonConverter(GetType(PayeezyErrorsConverter(Of PayeezyErrorMessage)))>
Public Messages As List(Of PayeezyErrorMessage)
Refactored code:
Public Class PayeezyRefundResponse
' [...]
<JsonProperty("Error")>
Public Errors As PayeezyErrors
End Class
Public Class PayeezyErrors
<JsonProperty("messages")>
<JsonConverter(GetType(PayeezyErrorsConverter(Of PayeezyErrorMessage)))>
Public Messages As List(Of PayeezyErrorMessage)
End Class
Public Class PayeezyErrorMessage
Public code As String
Public description As String
End Class
Custom converter:
► The writer part is not implemented, since you probably won't need to send back this JSON
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
Public Class PayeezyErrorsConverter(Of T)
Inherits JsonConverter
Public Overrides Function CanConvert(objectType As Type) As Boolean
Return (objectType = GetType(List(Of T)))
End Function
Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
Dim token As JToken = JToken.Load(reader)
If token.Type = JTokenType.Array Then
Return token.ToObject(Of List(Of T))()
End If
Return New List(Of T)() From {
token.ToObject(Of T)()
}
End Function
Public Overrides ReadOnly Property CanWrite() As Boolean
Get
Return False
End Get
End Property
Public Overrides Sub WriteJson(writer As JsonWriter, value As Object, serializer As JsonSerializer)
Throw New NotImplementedException()
End Sub
End Class

How To Deserialize JSON in vb,net with Multiple objects

Below is a json file that needs to be deserialized and to be stored in different variables.
With this current json, which is returned by an API, I am unable to deserialize because it gives me and error -
Please help me on deserializing this particular json
I have added the code i used, but it returns wrong values and null reference.
{
"result": {
"candidates": [
{
"similarity": 0.1330482513,
"person_id": "75741ea3-4d9b-4e25-8460-16444ee39946",
"descriptor_id": "2f228007-350e-4d58-9897-4b62e9978081",
"user_data": "Без названия (9)",
"external_id": null
}
],
"face": {
"id": "a1b224a3-60c6-4733-9bbc-136d53ea011c",
"score": 0.9320185781
}
},
"timestamp": 1569957900.1488559,
"source": "search",
"event_type": "match",
"authorization": {
"token_id": "71f9b3e0-51b1-480f-93b9-0e76e260bcbc",
"token_data": "first token"
},
"template": {
"descriptor_id": "a1b224a3-60c6-4733-9bbc-136d53ea011c"
},
"candidate": {
"list_id": "6e64e600-cd77-4894-940e-6f7022d8aba8",
"list_data": "FaceStream_search_list(DON'T DELETE)",
"list_type": 1
}
}
I have tried :
Public Class Rootobject
Public Property result As Result
Public Property timestamp As Single
Public Property source As String
Public Property event_type As String
Public Property authorization As Authorization
Public Property template As Template
Public Property candidate As Candidate1
End Class
Public Class Result
Public Property candidates() As Candidate
Public Property face As Face
End Class
Public Class Face
Public Property id As String
Public Property score As Single
End Class
Public Class Candidate
Public Property similarity As Double
Public Property person_id As String
Public Property descriptor_id As String
Public Property user_data As String
Public Property external_id As Object
End Class
Public Class Authorization
Public Property token_id As String
Public Property token_data As String
End Class
Public Class template
Public Property descriptor_id As String
End Class
Public Class Candidate1
Public Property list_id As String
Public Property list_data As String
Public Property list_type As Integer
End Class
''And used
Dim Candidatess As New Candidate
Candidatess = Newtonsoft.Json.JsonConvert.DeserializeObject(Of Candidate)((JObject.Parse(e.Message)).ToString)
msg(Candidatess.similarity.ToString)
msg(Candidatess.descriptor_id.ToString)
msg(Candidatess.person_id.ToString)
''REturns me Null
Public Class Candidate
Public Property similarity As Double
Public Property person_id As String
Public Property descriptor_id As String
Public Property user_data As String
Public Property external_id As Object
End Class
Public Class Face
Public Property id As String
Public Property score As Double
End Class
Public Class Result
Public Property candidates As Candidate()
Public Property face As Face
End Class
Public Class Authorization
Public Property token_id As String
Public Property token_data As String
End Class
Public Class Template
Public Property descriptor_id As String
End Class
Public Class Candidate
Public Property list_id As String
Public Property list_data As String
Public Property list_type As Integer
End Class
Public Class Candidates
Public Property result As Result
Public Property timestamp As Double
Public Property source As String
Public Property event_type As String
Public Property authorization As Authorization
Public Property template As Template
Public Property candidate As Candidate
End Class
Public Function GetData(ApiEndpoint As Uri, ApiToken As String)
Dim origResponse As HttpWebResponse = Nothing
Dim objResponse As HttpWebResponse = Nothing
Dim origReader As StreamReader = Nothing
Dim objReader As StreamReader = Nothing
Dim origRequest As HttpWebRequest = DirectCast(HttpWebRequest.Create(ApiEndpoint), HttpWebRequest)
origRequest.Headers.Add("Authorization", "Basic " & ApiToken)
origRequest.AllowAutoRedirect = False
origRequest.Method = "GET"
'Call the API and get the JSON Response data
origResponse = DirectCast(origRequest.GetResponse(), HttpWebResponse)
Dim Stream As Stream = origResponse.GetResponseStream()
Dim sr As New StreamReader(Stream, Encoding.GetEncoding("utf-8"))
Dim myJsonResponse As String = sr.ReadToEnd()
'Deserialize the Json
Dim objFormResults As Result = JsonConvert.DeserializeObject(Of Result)(myJsonResponse)
'loop through the results
End Function

Deserialize this JSON string

I always get the error:
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[Test.Form15+results[]]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'result', line 1, position 10.
My code is as follows and i'm not sure if it's the double-quotes causing the issues, or the bracket at the start of the json string. Any tips would be appreciated.
Public Class Form15
Public Class UTicketContact
<JsonProperty("display_value")>
Public Property DisplayValue As String
<JsonProperty("link")>
Public Property Link As String
End Class
Public Class URequestedFor
<JsonProperty("display_value")>
Public Property DisplayValue As String
<JsonProperty("link")>
Public Property Link As String
End Class
Public Class AssignedTo
<JsonProperty("display_value")>
Public Property DisplayValue As String
<JsonProperty("link")>
Public Property Link As String
End Class
Public Class OpenedBy
<JsonProperty("display_value")>
Public Property DisplayValue As String
<JsonProperty("link")>
Public Property Link As String
End Class
Public Class AssignmentGroup
<JsonProperty("display_value")>
Public Property DisplayValue As String
<JsonProperty("link")>
Public Property Link As String
End Class
Public Class Result
<JsonProperty("u_ticket_contact")>
Public Property UTicketContact As UTicketContact
<JsonProperty("u_requested_for")>
Public Property URequestedFor As URequestedFor
<JsonProperty("assigned_to")>
Public Property AssignedTo As AssignedTo
<JsonProperty("opened_by")>
Public Property OpenedBy As OpenedBy
<JsonProperty("assignment_group")>
Public Property AssignmentGroup As AssignmentGroup
End Class
Public Class results
<JsonProperty("result")>
Public Property Result As Result()
End Class
Function FindRequestedFor(ByVal instancename As String,
ByVal rtask As String) As String
Dim requestedfor As String = ""
'Dim byteArray As Byte() = Encoding.UTF8.GetBytes(postData)
Dim accessToken As String = GenerateToken("instancenameredacted",
"clientIdredacted",
"clientSecretredacted",
"accountredacted",
"accountpasswordredacted")
Dim url As String = "https://" & instancename & ".service-now.com/api/ubis2/request/rtask?query=number%3D" & rtask
Dim request As WebRequest = WebRequest.Create(url)
Dim dataStream As Stream
request.ContentType = "application/json; charset=utf-8"
request.Method = "GET"
request.Headers.Add("Authorization", "Bearer " & accessToken)
dataStream = request.GetResponse.GetResponseStream
Dim reader As New StreamReader(dataStream)
Dim responseFromServer As String = reader.ReadToEnd
'Format of the JSON string is: ""{
""result"": [
{
""u_ticket_contact"": {
""display_value"": ""Name1"",
""link"": ""https://instance.service-now.com/api/now/table/sys_user/470104cf600ad400808370bee6ad2596""
},
""u_requested_for"": {
""display_value"": ""Name2"",
""link"": ""https://instance.service-now.com/api/now/table/sys_user/470104cf600ad400808370bee6ad2596""
},
""assigned_to"": {
""display_value"": ""Name3"",
""link"": ""https://instance.service-now.com/api/now/table/sys_user/98c7a3e5ac723040773cf2044a10de0c""
},
""opened_by"": {
""display_value"": ""Name4"",
""link"": ""https://instance.service-now.com/api/now/table/sys_user/470104cf600ad400808370bee6ad2596""
},
""assignment_group"": {
""display_value"": ""Group Name1"",
""link"": ""https://instance.service-now.com/api/now/table/sys_user_group/bad979fa19c44a40b5a0d99e2b982e75""
}
}
]
}""
Console.WriteLine(responseFromServer)
reader.Close()
dataStream.Close()
Dim test = JsonConvert.DeserializeObject(Of List(Of results()))(responseFromServer)
End Function
end class
I would use List(Of Result) type with initialization as below:
Public Class results
<JsonProperty("result")>
Public Property Result As New List(Of Result)
End Class