Iterate Object Deserialized JSON - json

I cannot figure out how to iterate through an object to retrieve a list of errors sent in a JSON string. I have a For Each loop looing at each key pair value in my JSON but the third key pair is an object of key pairs. I cannot access these using the same For Each structure (I can access them if I loop through the object but want to keep it consistent if possible.. My 'Case Is "Errors" case statement is where I want to iterate the errors object but I am not sure how to get to it.. Here is my code.. I hope someone can assist..
Sample JSON:
{"success":"true","api_reference":3821,"errors":[{"record":"landlord","record_id":"-16::1::LPMB40-2385DDDC","error":"Please
ensure the email field has been
completed","error_code":"33101"},{"record":"landlord","record_id":"-16::1::LPMB40-2385DDDC","error":"Please
ensure the email field is a valid email
address","error_code":"33102"}]}
Dim jss = New JavaScriptSerializer()
Dim data = jss.Deserialize(Of Object)(responseFromServer)
Dim strSuccess = "", strAPIReference = ""
Dim intExpiresIn = 0
Dim ErrorsObject As Object
For Each kvp As KeyValuePair(Of String, Object) In data
Select Case kvp.Key
Case Is = "success"
strSuccess = kvp.Value
Case Is = "api_reference"
strAPIReference = kvp.Value
Case Is = "errors"
ErrorsObject = kvp.Value
For Each errorskvp As KeyValuePair(Of String, Object) In ErrorsObject
Next
End Select
Next

I would suggest doing this strongly typed, so that you can deserialize the json to a real object and use the object properties. That way it's much easier to read the values and loop errors etc:
Classes:
Public Class JsonResponse
Public Property Success As Boolean
Public Property Api_reference As String
Public Property Errors As IEnumerable(Of JsonError)
End Class
Public Class JsonError
Public Property Record As String
Public Property Record_Id As String
Public Property [Error] As String
Public Property Error_Code As String
End Class
Deserialization and use:
Dim j As New JavaScriptSerializer()
Dim data As JsonResponse = j.Deserialize(Of JsonResponse)(responseFromServer)
If Not data.Success Then
For Each myError As JsonError In data.Errors
Next
End If

Related

Json with parameters in Vb.net

I need to send json data to an API including a QR code and some other values.
this is what i got from them
The needed parameter is:
• Parameter "data" in JSON:
id -> 100 (fixed, it is the ID needed for our software)
qrcode -> QRcode value
Example: data={"id":"100","qrcode":"VL11bbdb186a3a6dcfc57a1b07149c9a0e"}
and this is the code i use
Call:
Dim jsonPost As New JsonPost(postadress)
Dim dictqr As New Dictionary(Of String, Object)
dictqr.Add("id", lastmeas.id)
dictqr.Add("qrcode", lastmeas.qrcode)
jsonPost.PostData(dictqr)
and this is the definition
Public Class JsonPost
Private urlToPost As String = ""
Public Sub New(ByVal urlToPost As String)
Me.urlToPost = urlToPost
End Sub
Public Function PostData(ByVal dictData As Dictionary(Of String, Object)) As Boolean
Dim webClient As New WebClient()
Dim resByte As Byte()
Dim resString As String
Dim reqString() As Byte
ServicePointManager.ServerCertificateValidationCallback = Function(o, certificate, chain, errors) True
Try
webClient.Headers("content-type") = "application/json"
webClient.Headers("accept") = "*/*"
reqString = Encoding.Default.GetBytes(JsonConvert.SerializeObject(dictData, Newtonsoft.Json.Formatting.None))
resByte = webClient.UploadData(Me.urlToPost, "POST", reqString)
resString = Encoding.Default.GetString(resByte)
Form1.respuesta_envio = resString
webClient.Dispose()
Return True
Catch ex As Exception
Form1.respuesta_envio = ex.Message
CreateObject("WScript.Shell").Popup(ex.Message, 5, "Data not transfered")
End Try
Return False
End Function
End Class
if i deserialize, i get
{"id":"100","qrcode":"example"}
but i do not know how to include this data= part
The API appears to be asking you to send a JSON string inside a form-url-encoded parameter. That's unpleasant and not a logical way to design an API, but if that's what they require then that's what you'll have to do.
Therefore you need to:
remove the Content-Type header telling the server to expect a JSON body in the request. What you'll actually be sending is form-url-encoded data where the one parameter happens to contain JSON within its value. i.e. remove this line:
webClient.Headers("content-type") = "application/json"
prepend the data= bit to the JSON string generated by the SerializeObject function:
reqString = Encoding.Default.GetBytes("data=" & JsonConvert.SerializeObject(dictData, Newtonsoft.Json.Formatting.None))

How to deserialize nested JSON arrays with Json.Net?

I want to deserialize the response of a HTTP-Request to Objects.
The Response looks like this:
[
"BeginOfEnumerable",
[
{
"StatusID": 12345,
"ItemID": 987654
}
],
"EndOfEnumerable"
]
I am using Newtonsoft.Json.
I tried to use Visual Studio's Edit > Paste special > Paste JSON as Classes to create the class model, but the result looks strange to me:
Public Class Rootobject
Public Property Property1() As Object
End Class
Also, this throws an Exception:
Dim myObject As Rootobject = JsonConvert.DeserializeObject(response.Content)
» Unexpected character encountered while parsing value: .Path ", line
0, position 0.
I want to get the StatusID and ItemID.
A JSON Validator I used says this JSON is valid.
The JSON structure is valid, per se, you may have some difficulty with the strings that don't follow the name:value pattern.
You could deserialize only the inner array of values, as a List(class), e.g.,
Imports System.Collections.Generic
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
Public Class EnumObject
Public Property StatusId As Long
Public Property ItemId As Long
End Class
'[...]
Dim jsonEnumsTokens = JArray.Parse(response.Content)
Dim enumsArray = jsonEnumsTokens.Children.Skip(1).First().ToObject(Of List(Of EnumObject))()
which returns the list of EnumObject that contain the values, if that's all you're interested in and you don't need to handle this JSON in any other way, or serialize it back in the same form.
If you want to get the JSON representation of the arrays only:
Dim justTheArraysJson = jsonEnumsTokens.Children.Skip(1).First().ToString()
In case you want to perform deserialization and serialization, maintaining the structure, you could use a custom JsonConverter that handles this case.
The EnumObjectsConverter creates an intermediate structure that contains both the single strings and the array of values, contained in the EnumObjectArray property.
This also allows to serialize back to the original structure, if needed.
Call it as:
Dim enumArray = EnumObjectsHandler.Deserialize(response.Content)
Dim serialized = EnumObjectsHandler.Serialize(enumArray)
The EnumObjectsHandler class that provides the static methods for the serialization:
Public Class EnumObjectsHandler
Private Shared settings As JsonSerializerSettings = New JsonSerializerSettings() With {
.Converters = {New EnumObjectsConverter()}
}
Public Shared Function Deserialize(json As String) As List(Of EnumObjectsRoot)
Return JsonConvert.DeserializeObject(Of List(Of EnumObjectsRoot))(json, settings)
End Function
Public Shared Function Serialize(data As List(Of EnumObjectsRoot)) As String
Return JsonConvert.SerializeObject(data, settings)
End Function
Public Class EnumObject
Public Property StatusId As Long
Public Property ItemId As Long
End Class
Public Structure EnumObjectsRoot
Public Property EnumObjectArray As List(Of EnumObject)
Public Property Operation As String
Public Shared Widening Operator CType(objectArray As List(Of EnumObject)) As EnumObjectsRoot
Return New EnumObjectsRoot With {.EnumObjectArray = objectArray}
End Operator
Public Shared Widening Operator CType(op As String) As EnumObjectsRoot
Return New EnumObjectsRoot With {.Operation = op}
End Operator
End Structure
Friend Class EnumObjectsConverter
Inherits JsonConverter
Public Overrides Function CanConvert(t As Type) As Boolean
Return t Is GetType(EnumObjectsRoot)
End Function
Public Overrides Function ReadJson(reader As JsonReader, t As Type, existingValue As Object, serializer As JsonSerializer) As Object
Select Case reader.TokenType
Case JsonToken.String
Dim stringValue = serializer.Deserialize(Of String)(reader)
Return New EnumObjectsRoot() With {
.Operation = stringValue
}
Case JsonToken.StartArray
Dim arrayValue = serializer.Deserialize(Of List(Of EnumObject))(reader)
Return New EnumObjectsRoot() With {
.EnumObjectArray = arrayValue
}
End Select
Throw New Exception("EnumObjectsRoot could not be deserialized")
End Function
Public Overrides Sub WriteJson(writer As JsonWriter, untypedValue As Object, serializer As JsonSerializer)
Dim value = CType(untypedValue, EnumObjectsRoot)
If value.Operation IsNot Nothing Then
serializer.Serialize(writer, value.Operation)
Return
End If
If value.EnumObjectArray IsNot Nothing Then
serializer.Serialize(writer, value.EnumObjectArray)
Return
End If
Throw New Exception("EnumObjectsRoot could not be serialized")
End Sub
End Class
End Class

Error While serializing object to json format using JsonConvert.SerializeObject function

I have a method to serialize object to json format. the object contains nested objects and lists. but i face this error :
Error getting value from 'Length' on 'Microsoft.VisualStudio.Web.PageInspector.Runtime.Tracing.ArteryFilter'.
Dim serilaize As New JsonSerializerSettings()
With serilaize
.PreserveReferencesHandling = PreserveReferencesHandling.Objects
End With
Dim strProgram As String = JsonConvert.SerializeObject(ProgramObject, Formatting.Indented, serilaize)
Any help please !
Thanks
This works:
Module Module1
Sub Main()
Dim ProgramObject = New TestObject()
ProgramObject.Items = New List(Of String)
ProgramObject.Items.Add("testitem")
Dim serialize As New Newtonsoft.Json.JsonSerializerSettings()
With serialize.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects
Dim strProgram As String = Newtonsoft.Json.JsonConvert.SerializeObject(ProgramObject, Newtonsoft.Json.Formatting.Indented, serialize)
End With
End Sub
End Module
TestObject looks like this:
Public Class TestObject
Property Items As List(Of String)
End Class

How to deserialize a JSON object containing two arrays

I'm using VB.Net, MVC 5. I'm creating a javaScript object then passing that object to my controller using ajax and JSON.
My object is created like this:
var myEdits = {
arrayOfIDs: [],
arrayOfValues : []
};
This is how I send the object to the server:
$.ajax({
url: '/ViewDetails/EditConfirmation',
type: 'POST',
data: { 'myEdits': myEdits }
})
.success(function (result) {
alert("success");
})
.error (function (status) {
alert(status);
})
My string when it hits the server looks like this:
"{"arrayOfIDs":["53","54","55","56"],"arrayOfValues":["foo","bar","narf","woohoo"]}"
I've tried creating a class like this:
Function CompareEdits(myEdits As Object) As IEnumerable(Of compareEdits)
Dim serializer As New JavaScriptSerializer()
Dim model As compareEdits
model = serializer.Deserialize(Of compareEdits)(myEdits)
Return model
End Function
End Class
Public Class compareEdits
Public Property arrayOfIDs As List(Of String)
Public Property arrayOfValues As List(Of String)
End Class
I've also tried deserializing it like this:
Function CompareEdits(myEdits As Object) As IEnumerable(Of compareEdits)
Dim serializer As New JavaScriptSerializer()
Dim model
model = serializer.Deserialize(Of Array)(myEdits)
Return model
End Function
I keep getting this error when I try to deserialize my JSON string:
{"Conversion from type 'String()' to type 'String' is not valid."}
The first array in the string is used to decide which field to update, the second array in the string is the actual value.
How do I properly deserialize this string?
Your first attempt is mostly correct:
' the serialized data is string, dont box it
' the return is a Type containing the Lists/Arrays
Function CompareEdits(myEdits As String) As compareEdits
Dim serializer As New JavaScriptSerializer()
Dim model = serializer.Deserialize(Of compareEdits)(myEdits)
Return model
End Function
The return Type is definitely wrong: you are deserializing to a Type which contains the 2 arrays/lists, so As IEnumerable isnt right.
I'm not sure why you get the error or where, I accidentally typed it in without those 2 aspects and it worked fine. The error mentioned likely to result from the second method.

POST using the uploadstring method to call a web service and pass a json array

I am attempting to do a POST to a web service. I am using the WebClient class and calling the uploadstring method. This works fine until the web service I call expects some data, particularly a json array. I am trying to find out what format the data needs to be in, in order for the web service to accept and consume it properly. Example:
WebClient myWebClient = new WebClient();
string resp = myWebClient.UploadString("www.myUrl.com", "POST", "someDataToSend");
Any help here would be appreciated!
the web service (vb.net) being called takes a keyvaluepair:
<OperationContract(), WebInvoke(BodyStyle:=WebMessageBodyStyle.WrappedRequest, Method:="POST", RequestFormat:=WebMessageFormat.Json, ResponseFormat:=WebMessageFormat.Json)> _
Public Function DoSomething(ByVal myKeyValuePair() As KeyValuePair(Of String, String)) As String
I found a solution for this. The data has to be in json format literally:
"{"Type":[{"key":"cType","value":"Age"}]}"
I created a class serialized it and then finagled the square brackets in.
Public Class cType
Private _key As String
Public Property Key() As String
Get
Return _key
End Get
Set(ByVal value As String)
value = "cType"
_key = value
End Set
End Property
Public value As String
End Class
Dim objType As cType = New cType
objType.value = "Age"
Dim myData As String = deserializer.Serialize(New With {.cType = objType})
myData = myData.Insert(12, "[")
myData = myData.Insert(myData.Length - 1, "]")