I'm using JSon.net to deserialize a json object i'm getting from the GravityForms Web API.
The json that I get back is this...
{"status":200,"response":{
"12":{"id":"12","title":"Test Form","entries":"1"},
"1":{"id":"1","title":"What's My Home Worth?","entries":"92"}
}
}
My VB.net Object that I'm deserializing into is
Namespace Forms
Public Class GFForm
Public Property id As String
Public Property title As String
Public Property entries As String
End Class
Public Class Response
<JsonProperty("1")>
Public Property GFForms() As GFForm
End Class
Public Class TopLevel
Public Property status As Integer
Public Property response As Response
End Class
End Namespace
and I am executing the JsonConvert statement like this..
Dim obj As GravityForms.Forms.TopLevel
obj = JsonConvert.DeserializeObject(Of GravityForms.Forms.TopLevel)(str)
It seems to successfully deserialize the json into my vb object but I am only getting 1 response object. I should be getting 2 of them right?
The odd thing is that the GFForm that I'm getting is the second one (ID:1), which makes it seem like it's over writing the value of the first object (ID:12).
Any help would be great because I've been messing with this for the better part of 2 days and I'm lost.
Edit:
This was not clear in my question above. I do not know the number of GFForm objects that I get back from the web service. It could be 2 (like in the example) or it could be 32 or 45 or whatever.
I'd like to put the GFForm objects in something I can bind to a datagridview
You have two GFForm properties in your response, but one Response object with one property to fill. Maybe you should try using something like that
Namespace Forms
Public Class GFForm
Public Property id As String
Public Property title As String
Public Property entries As String
End Class
Public Class Response
<JsonProperty("1")>
Public Property GFForms1 As GFForm
Public Property GFForms12 As GFForm
End Class
Public Class TopLevel
Public Property status As Integer
Public Property response As Response
End Class
End Namespace
EDIT: If you don't know the number of response properties, try creating a new Response object for each property.
Related
Having trouble to read json return in a useful way
Searching "all over" to find how to create classes and how to de-serialize json return
This is the json return:
[[{"metadata":{},"contentType":0,"contentId":0,"objectName":"Mi","objectId":"1","classId":"118"},
{"metadata":{},"contentType":0,"contentId":0,"objectName":"BA","objectId":"224445","classId":"103"},
{"metadata":{},"contentType":0,"contentId":0,"objectName":"1","objectId":"239011","classId":"104"},
{"metadata":{},"contentType":0,"contentId":0,"objectName":"1","objectId":"239309","classId":"105"}]]
Tried Visual Studio (VB.net) Paste Special to create json classes, but I can't seem to get my head around how to use it. Using Newtonsoft.Json.
These are the classes, how do I deserialize json and make it useful?
Public Class Rootobject
Public Property Property1()() As Class1
End Class
Public Class Class1
Public Property metadata As Metadata
Public Property contentType As Integer
Public Property contentId As Integer
Public Property objectName As String
Public Property objectId As String
Public Property classId As String
End Class
Public Class Metadata
End Class
Your JSON is an array of arrays of Class1 objects, so you need to deserialize to that.
Dim data As Class1()() = JsonConvert.DeserializeObject(Of Class1()())(json)
You don't actually need the Rootobject class here.
Working demo: https://dotnetfiddle.net/1JuaYk
I have this JSON data:
{"asks":[["0.26039995",19.91610429],["0.26063345",3070.562292]],"bids":[["0.26000017",30381.45513902],["0.26000000",8299.1410574]],"isFrozen":"0","seq":50663190}
I wrote this code:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim wc As New WebClient
Dim sURL As String = "https://poloniex.com/public?command=returnOrderBook¤cyPair=USDT_STR&depth=" & 2
Dim res As String = wc.DownloadString(New Uri(sURL))
Dim m As IEnumerable(Of Rootobject) = JsonConvert.DeserializeObject(Of IEnumerable(Of Rootobject))(res)
End Sub
Public Class Rootobject
Public Property asks As asksDef()
Public Property bids As bidsDef()
Public Property isFrozen As String
Public Property seq As Integer
End Class
Public Class asksDef
Public Property priceAsk As String
Public Property quantAsk As Integer
End Class
Public Class bidsDef
Public Property priceBid As String
Public Property quantBid As Integer
End Class
I've pasted the JSON class with VB paste special.
The question is: how to access to every ask, every bid and the isFrozen and seq values.
I got an error on this line:
Dim m As IEnumerable(Of Rootobject) = JsonConvert.DeserializeObject(Of IEnumerable(Of Rootobject))(res)
The error message I got is:
An unhandled exception of type
'Newtonsoft.Json.JsonSerializationException' occurred in
Newtonsoft.Json.dll
Additional information: Cannot deserialize the current JSON object
(e.g. {"name":"value"}) into type
'System.Collections.Generic.IEnumerable`1[poloniexAPI.Rootobject]'
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 'asks', line 1, position 8.
I'm stuck again this time with this JSON model. How to proceed with this?
{"BTC_BCN":{"id":7,"last":"0.00000042","lowestAsk":"0.00000043","highestBid":"0.00000042","percentChange":"0.00000000","baseVolume":"179.56364789","quoteVolume":"436786711.33832335","isFrozen":"0","high24hr":"0.00000043","low24hr":"0.00000039"},"BTC_BELA":{"id":8,"last":"0.00002091","lowestAsk":"0.00002097","highestBid":"0.00002091","percentChange":"-0.10831556","baseVolume":"12.57891843","quoteVolume":"579476.06165462","isFrozen":"0","high24hr":"0.00002345","low24hr":"0.00002088"}}
The root cause of this specific error is that your JSON represents a single object (which contains some arrays and other info) but you are trying to deserialize it as if the whole thing were enumerable. However, fixing this will not solve the whole problem; there are a couple of other issues as well.
This JSON is a little odd because it uses an array to group together each price and quantity pair for the bids and asks, whereas an object seems like it would be more appropriate (and more easily consumable). Since Json.Net does not have a facility to automatically map an array into class properties by index, you will need to use a custom JsonConverter to deserialize this data properly. Also, the prices are represented as strings for some reason where they should be decimals like the quantity. This can be handled in the converter as well.
Before we get to the converter, let's fix your class definitions. Since the bids and asks use the same structure, I would recommend defining a common class for that. Both price and quantity properties should be declared as Decimal:
Public Class PriceQuantityPair
Public Property price As Decimal
Public Property quantity As Decimal
End Class
Then define your root class like this:
Class RootObject
Public Property asks As List(Of PriceQuantityPair)
Public Property bids As List(Of PriceQuantityPair)
Public Property isFrozen As String
Public Property seq As Integer
End Class
Here is the code for the converter, which will translate the array structure for each pair into a PriceQuantityPair instance:
Class PriceQuantityPairConverter
Inherits JsonConverter
Public Overrides Function CanConvert(objectType As Type) As Boolean
Return objectType Is GetType(PriceQuantityPair)
End Function
Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
Dim ja As JArray = JArray.Load(reader)
Dim pair As PriceQuantityPair = New PriceQuantityPair()
pair.price = ja(0).ToObject(Of Decimal)()
pair.quantity = ja(1).ToObject(Of Decimal)()
Return pair
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
To use the converter, add a <JsonConverter> attribute to the PriceQuantityPair class like this:
<JsonConverter(GetType(PriceQuantityPairConverter))>
Public Class PriceQuantityPair
...
End Class
Finally, deserialize the JSON into the RootObject class like this:
Dim root As RootObject = JsonConvert.DeserializeObject(Of RootObject)(json)
Here is a demo: https://dotnetfiddle.net/dDHLtR
As far as I understand your question.
You can access the properties with the 'm' variable where you are storing the de serialized data.
Ex: m.isFrozen, m.seq, m.bids() & m.asks().
I am new to manipulating JSON format data retrieved through an Web API. I'm using Newtonsoft.Json.JsonConvert to deserialize and assign to datatable.
This is the JSON data I am trying to get into a datatable.
[{
"classDesc":"SIDEWALK,DRIVEWAY,CURB",
"classCode":"EH",
"legend":"017",
"isActive":"Y",
"atrSpaCityDistrictId":"00D17209F8F25F6D4A00011302",
"atrSpaCitieDistrict":{
"cityDistrict":"",
"isActive":"1",
"atrSpaClassLegends":null,
"id":"00D17209F8F25F6D4A00011302"
},
"id":"00D1748B8DA0AB0A7400011202"
}]
I have created the below classes
Public Class RootObject
Public Property classDesc As String
Public Property classCode As String
Public Property id As Integer
Public Property legend As Integer
Public Property isActive As String
Public Property atrSpaCityDistrictId As Integer
Public Property atrSpaCitieDistrict As List(Of Result) End Class
Public Class Result
Public Property cityDistrict As String
Public Property isActive As Integer
Public Property atrSpaClassLegends As List(Of Legend)
Public Property id As Integer
End Class
Public Class Legend
End Class
Below is my VB.Net code:
Dim table As DataTable Dim client As New HttpClient() client.BaseAddress = New Uri("http://localhost:5000/") client.DefaultRequestHeaders.Accept.Add(New MediaTypeWithQualityHeaderValue("application/json"))
Dim response As HttpResponseMessage = client.GetAsync("api/spaclasslegend").Result
If response.IsSuccessStatusCode Then
Dim json As String = response.Content.ReadAsStringAsync().Result table = JsonConvert.DeserializeObject(Of DataTable)(json)
End If
Getting below error
"Cannot deserialize the current JSON array (e.g. [1,2,3]) into type
'Alco.APTIS.Services.RootObject' because the type requires a JSON
object (e.g. {"name":"value"}) to deserialize correctly."
I have tried different ways to fix this using stackoverflow.com and finally posting here for help.
You have two unrelated issues.
Firstly, your root object doesn't match your JSON. If I copy your JSON into a code generator such as http://jsonutils.com/, I get the following, using a List(Of Legend) for the null atrSpaClassLegends property:
Public Class AtrSpaCitieDistrict
Public Property cityDistrict As String
Public Property isActive As String
Public Property atrSpaClassLegends As List(Of Legend)
Public Property id As String
End Class
Public Class RootObject
Public Property classDesc As String
Public Property classCode As String
Public Property legend As String
Public Property isActive As String
Public Property atrSpaCityDistrictId As String
Public Property atrSpaCitieDistrict As AtrSpaCitieDistrict
Public Property id As String
End Class
Public Class Legend
End Class
Having done this, it is now possible to deserialize your JSON into a List(Of RootObject):
Dim root = JsonConvert.DeserializeObject(Of List(Of RootObject))(jsonString)
Note you must deserialize as a List(Of RootObject) (or similar .Net collection such as an array) since your top level JSON container is a JSON array -- an ordered comma-separated sequence of values surrounded by [ and ]. This is explained in the Json.NET Serialization Guide. Sample fiddle.
Secondly, despite having created these types, in the code shown in your question you are not using them at all! Instead, you are deserializing to a DataTable. And unfortunately the atrSpaCitieDistrict property is a nested object:
{
"atrSpaCitieDistrict": {
"cityDistrict": "",
"isActive": "1",
"atrSpaClassLegends": null,
"id": "00D17209F8F25F6D4A00011302"
},
}
Json.NET does not support automatically deserializing column values that are complex objects into untyped data tables, and will throw an exception if one is encountered. Instead, you would need to deserialize into a typed data table. However, this may be a typo in your question; the exception error message indicates you are actually trying to deserialize into an object of type Alco.APTIS.Services.RootObject and not a DataTable.
Hello I need to convert this objetct to vb.
{"user":
[
{"name":"CompanyName"},
{"password":"CompanyPassword"},
{"email":"mail#company.com"},
{"name":"UserName"},
{"email":"user#mail.com"}
]
}
I try with this:
Public Class InfoObjUser
Public Property name As String
Public Property password As String
Public Property email As String
End Class
Public Class ObjUser
Public Property user As New List(Of InfoObjUser)
End Class
but when I go to serialize json object created in vb
I see that there are no curly brackets.
Also in vb I can't add {"name":"UserName"},{"email":"user#mail.com"}
because they are already present.
Take a look at this: JSON Serialization in .Net.
You need to add the System.Runtime.Serialization as reference to your project, and then set up a serializer object in your code. You also need to tag, which fields in your class match your JSON code.
This would be your class setup:
<DataContract>
Public Class InfoObjUser
<DataMember(Name:="Name")>
Public Property name As String
<DataMember(Name:="Password")>
Public Property password As String
<DataMember(Name:="Email")>
Public Property email As String
End Class
<DataContract>
Public Class ObjUser
<DataMember>
Public Property user As New List(Of InfoObjUser)
End Class
And a Json reader class for that would look like this:
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Json
Public Class JsonReader
Public Shared Function FromString(Of T)(ByVal input As String) As T
Dim serializer As New DataContractJsonSerializer(GetType(T))
Dim memStream As New MemoryStream()
Dim sw As New StreamWriter(memStream)
sw.Write(input)
sw.Flush()
memStream.Position = 0
Dim returnObj As T = CType(serializer.ReadObject(memStream), T)
Return returnObj
End Function
End Class
And finally, you can call this class like this:
Dim jsonString ' = ...Input string here
Dim user As ObjUser = JsonReader.FromString(Of ObjUser)(jsonString)
However, it is not possible to have the name for two different data objects, as the serializer would not know where to map them to, as it goes by Object name.
I don't know how established this data structure already is, but if it's possible, I would suggest you to change the duplicated names, as no real mapping can occur when doing so programmatically.
<DataMember(Name:="UserName")>
Public Property username As String
<DataMember(Name:="UserEmail")>
Public Property usermail As String
If you would add something like this to your data model class and rename the field names in your Json, then it would work.
I need to validate a JSON list similar to the following:
[{"op":"A","path":"C","value":"B"},...]
in a Spring MVC application - I am currently deserializing (using default Jackson) to an object along the lines of:
public class Operations extends ArrayList<Operation>{}
public class Operation {
#NotEmpty
public String op;
#NotEmpty
public String path;
public Object value;
public void setOp(String op)... and other getters/setters
}
but I cannot figure out how to get jsr303 validation provided by reference hibernate implementation to fire for the attributes of Operation.
I can get it to function if I wrap the list in a class but then I have an incorrect format for the JSON, ie something like:
{"ops":[{"op":"A",...},...]}
is it possible to validate the first object (Operations)? and if not is it possible to serialize the first format (ie the JSON list) to an object of the second format (ie a list wrapped in a placeholder object with a placeholder field)
Update
Having failed to find a way to trigger the jsr303 validation on a bare ArrayList I have written a custom jackson json deserializer to stick it into a containing object with an annotated field along the lines of
#JsonDeserialize(using=OperationsDeserializer.class)
public class Operations {
#NotEmpty
private ArrayList<Operation> ops;
public void setOps(ArrayList<Operation>ops)...
public ArrayList<Operation> getOps()...
}
This works but now any autogenerated documentation for my api is generating json examples with the dummy "ops" field in it - ie {"ops" : [ ... ] }
so the search for a method of triggering jsr303 validation on an ArrayList that is not a field of another object continues - perhaps there is a way to inject a proxy wrapping class at runtime that might work around this?
Use ObjectMapper.class. it has a method which will convert Json Object into Class Object
method is , new ObjectMapper().readValue(String str, Class<T> valueType)
So you can iterate your Object array, convert to string and pass it to this method to get your result.
so it would look like,
new ObjectMapper().readValue(object.toString, Operation.class);