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.
Related
I have a Controller that defines a number of Get methods. The Razor Component is able to read all the Gets using GetFromJsonAsync() without any issue. However, one of the Get methods returns a string object. The Razor Component keeps blowing up when trying to read that string.
MyController.cs
[HttpGet("GetObject")]
public async Task<MyObject> GetObject(int? id)
{
MyObject obj = new MyObject();
// ... do some work here and fill in obj
return obj;
}
[HttpGet("GetString")]
public async Task<string> GetString(int? id)
{
string retval = "";
// ... do some work here and fill in retval
return retval;
}
MyComponent.razor
// this call works
MyObject myObj = await _http.GetFromJsonAsync<string>("My/GetObject?id=15");
// this call throws a Json syntax error
string myString = await _http.GetFromJsonAsync<string>("My/GetString?id=15");
I'm not sure why the system is able to read all my objects with the exception of the string object. Has anyone else run into this issue with being unable to read strings from the Controller?
I finally figured out what is going on. It appears that if your Controller is returning a string object, Blazor is assuming that you have already converted your data into a true Json string and will not attempt to serialize it into Json for you. So I had to serialize it myself on the Controller side. Then my Razor Component picked up the original string as intended. Here is the solution:
[HttpGet("GetString")]
public async Task<string> GetString(int? id)
{
string retval = "";
// ... do some work here and fill in retval
return System.Text.Json.JsonSerializer.Serialize<string>(retval);
}
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
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
I am working in VS 2015 and c#.
I have a Json String which has a list of collections, each collection represents an object,
string wsjson =
"{
"customAttributes":
[{"description":"xxxxxxx","id":11,"value":"xxxxxxx"},{"description":"xxxxxxx","id":10,"value":"xxxxxxx"}],
"location":{"account":"xxxxxxx","cabinet":"xxxxxxx"},
"misc":{"approved":false,"archived":false,"deleted":false,"echo":true,"external":false,"favorite":false,"officialLocked":false,"signed":false},
"permissions":[{"xxxxxxx":true,"xxxxxxx":false,"edit":true,"noAccess":false,"share":true,"view":true}],
"standardAttributes":{"aclStatus":"xxxxxxx","created":"\/Date(xxxxxxx)\/","createdBy":"xxxxxxx","createdByGuid":"xxxxxxx","envId":"xxxxxxx","extension":"ndws","id":"xxxxxxx","modified":"\/Date(xxxxxxx)\/","modifiedBy":"xxxxxxx","modifiedByGuid":"xxxxxxx","name":"xxxxxxx","officialVer":1,"size":4,"syncMod":xxxxxxx,"url":"xxxxxxx","versions":1}}"
DataSet wsdataSet = JsonConvert.DeserializeObject<DataSet>(wsjson);
I am getting an error. I tried to follow this (Deserializing Json String into multiple Object types) solution but I am getting error for this line as my jason data is in a string and no function to parse string.
var j = JArray.Parse(data);
Here is the visual image of the jason data.
Actual code block in my program is:
foreach (DataRow row in dataTable.Rows)
{
string wsjson = GetWorkspaceProfile(row[0].ToString());
DataSet wsdataSet = JsonConvert.DeserializeObject<DataSet>(wsjson);
DataTable wsdataTable = wsdataSet.Tables["standardAttributes"];
foreach (DataRow wsrow in wsdataTable.Rows)
{
cmbWorkspaceByCabinet.Items.Add(new KeyValuePair<string, string>(row["envId"].ToString(), wsrow["name"].ToString()));
}
}
Where GetWorkspaceProfile is a string type return function which return me JSON data as string like the image above.
public string GetWorkspaceProfile(string WorkspaceId)
{
string responseStr = "";
string url = "v1/Workspace/" + WorkspaceId + "/info";
RestType type = RestType.GET;
Boolean useXml = false;
RestRequest rr = FormRequest(type, url, useXml);
IRestResponse response;
try
{
response = executeRequest(rr);
responseStr = response.Content;
}
catch (Exception ex)
{
return null;
}
return responseStr;
}
JArray.Parse will not work, because you don't have a json array, it is an object. Also not the all values of that object are collections, for example location is also object, not a collection. You have some options to parse it
Parse root object into Dictionary
JsonConvert.DeserializeObject<Dictionary<string, string>>(wsjson)
then parse every value of the dictionary to array if value is array and to dictionary if value is object.
Create a C# class according to your json data and parse string directly into instance of that class
JsonConvert.DeserializeObject<JsonModel>(wsjson);
where JsonModel is the class you need to create.
You can use JArray and JToken to get the values you want using json path.
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, "]")