vb.net Serializing Collections unable to add a collection to object? - json

I'm trying to generate some JSON that looks like this:
{
"#type": "MessageCard",
"sections": [
{
"activityTitle": " Request",
"facts": [
{
"name": "name1",
"value": "Value"
},
{
"name": " Date:",
"value": "Value Date"
}
],
"text": "Some Test."
}
],
"potentialAction": [
{
"#type": "ActionCard",
"name": "Add a comment",
"inputs": [
{
"#type": "TextInput",
"id": "comment",
"isMultiline": true
}
]
}
]
}
I performed a paste special into VS and it generated the class structure for me as such:
Public Class MessageCard
Public Property type As String
Public Property context As String
Public Property summary As String
Public Property themeColor As String
Public Property sections() As Section
Public Property potentialAction() As Potentialaction
End Class
I'm trying to add the sections to the object as such:
Dim m as New MessageCard
Dim s As New List(Of Section)
s.Add(s1)
s.Add(s2)
m.sections = s
The compiler complains that it cannot convert a list of Sections into a Section. Did the class get generated incorrectly, or am i constructing it incorrectly?

First, your JSON is not quite complete and the Classes you show wont create that JSON.
As posted, that JSON simply shows a Sections and potentialAction class which are not related in any way. An enclosing [ ... ] is needed to represent the MessageCard class containing the two of them.
[{
"#type": "MessageCard",
...
}]
Next, the class you have shows all sorts of things not present in the JSON: context, summary and themeColor for instance. I assume those might be missing for brevity, but it is confusing. There is also 2 other Types missing which are in the JSON, Fact and Input.
Corrected, the classes should be:
Public Class MsgCard
<JsonProperty("#type")>
Public Property ItemType As String
Public Property sections As List(Of Section)
Public Property potentialAction As List(Of Potentialaction)
Public Sub New()
sections = New List(Of Section)
potentialAction = New List(Of Potentialaction)
End Sub
End Class
Public Class Section
Public Property activityTitle As String
Public Property facts As Fact()
Public Property text As String
End Class
Public Class Fact
Public Property name As String
Public Property value As String
End Class
Public Class Potentialaction
<JsonProperty("#type")>
Public Property ActionType As String
Public Property name As String
Public Property inputs As Input()
End Class
Public Class Input
<JsonProperty("#type")>
Public Property InputType As String
Public Property id As String
Public Property isMultiline As Boolean
End Class
Notes
You did not specify a JSON serializer, so this is prepared to JSON.NET as recommended by Microsoft.
#type is an illegal property name, so the JsonProperty attribute is used to create an alias. I also used less confusingly redundant names.
You may want to change Fact and Input to List(Of T) if you will be creating and pushing them into the class object as well.
Finally, for the actual question you asked, most of the automatic class generators have trouble with arrays (even VS).
Public Property sections() As Section
' should be:
Public Property sections As Section()
That simply declares that sections will be an array, it does not create the array. Normally this is not a problem because the Serializer/Deserializer will create the array. To allow code external to the class to add to them, you probably want to use a List as the classes above do, then create the instance in the constructor:
Public Sub New()
sections = New List(Of Section)
potentialAction = New List(Of Potentialaction)
End Sub

Related

Serialize datatable with bindingsource to Json

I have a REST API from which I get the JSON data back.
The JSON model looks like the following:
{
"Id": "",
"Name": "",
"ExternalId": "",
"Headers": [
{
"Name": "",
"DisplayAt": ""
}
],
"Rows": [
"Array[string]"
],
"NewRows": [
"Array[string]"
],
"DeletedRows": [
"Array[string]"
],
"CompanyId": 0,
"IntegrationKey": ""
}
I've made a Class model that looks like the following:
Imports Newtonsoft.Json
Namespace Models
Public Class Header
<JsonProperty("Name")>
Public Property Name As String
<JsonProperty("DisplayAt")>
Public Property DisplayAt As String
End Class
Public Class DataSource
<JsonProperty("Id")>
Public Property Id As String
<JsonProperty("Name")>
Public Property Name As String
<JsonProperty("Headers")>
Public Property Headers As Header()
<JsonProperty("Rows")>
Public Property Rows As String()()
<JsonProperty("TotalRows")>
Public Property TotalRows As Integer
<JsonProperty("LastUpdated")>
Public Property LastUpdated As DateTime
<JsonProperty("CompanyId")>
Public Property CompanyId As Integer
End Class
Public Class Category
<JsonProperty("DataSource")>
Public Property DataSource As DataSource
End Class
End Namespace
From the array rows I retrieve all my necessary data which is saved in a datatable. Via a BindingSource all the fields are bound to the listbox and all changes are saved to the datatable.
The JSON is deserialized with NewtonSoft.
Now I want to save the changes back to the database via a PUT statement. Therefore I have to serialize the datatable.
I can do that with the following code:
json = JsonConvert.SerializeObject(datatable, Formatting.Indented)
In this case I'm getting only the array from the Rows in a nice JSON format.
My first question is:
How do I serialize the datatable so that I can also pass the ID and externalID in my JSON?
My second question:
Does it updates all the datarows from the database or is it also possible to just update the changed rows?

Deserialize nested JSON and VB.Net

I try to get the values from the basic section in the following json result
{
"responseCode": "Ok",
"responseMessage": "",
"ssnStatus": "Active",
"basic": {
"firstName": "Testnamn",
"givenName": "Gettnamn",
"surName": "Testname",
"middleName": null,
"lastName": "Lastname",
"co": null,
"street": "Teststreet lgh 1202",
"zipCode": "92609",
"city": "Stad"
},
"phoneNumbers": {
"phoneNumbers": []
},
"ssnStatusBlock": null
}
I can get the first level (ssnStatus) with the code below, but how do I get the firstName, givenName etc?
Dim post As Post = JsonConvert.DeserializeObject(Of Post)(exampleJson)
Dim ssnStatus As String = post.ssnStatus
and
Public Class Post
Public Property ssnStatus As String
End Class
You are missing the properties and classes definition for all the other membersof the JSON object.
Create a new class file in your Project. Give it a name that properly describe the JSON usage,
add the Imports Newtonsoft.Json import,
copy a sample of the JSON object that describes the JSON structure (the one you have here is good),
position the caret inside the new class definition,
see the Visual Studio menu: Edit -> Paste Special -> Paste JSON as classes
Visual Studio will create all the classes and properties needed to handle the JSON object you selected.
Note: With more complex classes, it may happen that the result Visual Studio produces is not exactly what you require. In this case, try one of the specialized WebSites that provide a free conversion service:
Json Utils (VB.Net, C#, Java, Javascript, more...)
QuickType (C#, C++, Java, Javascript, Python, Go, more...)
json2csharp (C#)
JSON Formatter (JSON formatting and validation)
The new root class definition will be named Rootobject. Change this name as needed,
to make it more clear what the class is used for.
This is the class definition that Visual Studio creates with the JSON object in your question.
I created a class Project class named MyWebSitePost, created the JSON bject class definition as previously described, I then renamed the default master class Post, replacing the default Rootobject name:
Public Class MyWebSitePost
Public Class Post
Public Property responseCode As String
Public Property responseMessage As String
Public Property ssnStatus As String
Public Property basic As Basic
Public Property phoneNumbers As Phonenumbers
Public Property ssnStatusBlock As Object
End Class
Public Class Basic
Public Property firstName As String
Public Property givenName As String
Public Property surName As String
Public Property middleName As Object
Public Property lastName As String
Public Property co As Object
Public Property street As String
Public Property zipCode As String
Public Property city As String
End Class
Public Class Phonenumbers
Public Property phoneNumbers() As Object
End Class
End Class
You can then use the code you already have to access all the other properties:
(Some Properties type may have been set to Object; modify as
required).
Dim JsonPost As Post = JsonConvert.DeserializeObject(Of Post)(exampleJson)
Dim ssnStatus As String = JsonPost.ssnStatus
Dim FirstName As String = JsonPost.basic.firstName
and so on.
Note:
As you can see, all properties have the default name, as defined in the JSON object. Some properties names are not really adeguate to describe thier content. For example the co property is probably the Country name. To change the property name, you can use the <JsonProperty> attribute, which references the JSON object original name and use a custom name for the Property:
'(...)
<JsonProperty("co")>
Public Property Country As Object
'(...)
You can then access this Property using the custom name:
Dim CountryName As String = JsonPost.basic.Country

JSON class creation help in VB.NET [duplicate]

I am very new to json, JSON.net and all that. After reading similiar questions here I cannot get my code working.
What exactly is my error? What have I overseen?
Is it possible to skip the classes "links" and "meta" for testing purposes or do I have to define EVERY property?
I have got the following REST output:
{
"codes" : [
{
"href" : "https://www.someserver.com/form_definitions/OIlG4GxMyeh0sdrt3AYuaXbauGicW71M/field_definitions/zFEova6LiPM/codes/4Sxnr961xzM",
"rel" : "document_field_definition_code",
"title" : "TITLE 1"
},
{
"href" : "https://www.someserver.com/form_definitions/OIlG4GxMyeh0sdrt3AYuaXbauGicW71M/field_definitions/zFEova6LiPM/codes/buho0CsLc5k",
"rel" : "document_field_definition_code",
"title" : "TITLE 2"
},
{
"href" : "https://www.someserver.com/form_definitions/OIlG4GxMyeh0sdrt3AYuaXbauGicW71M/field_definitions/zFEova6LiPM/codes/RvQoykUM_Sk",
"rel" : "document_field_definition_code",
"title" : "TITLE 3"
}
],
"links" : [
{
"about" : "https://www.someserver.com/form_definitions/OIlG4GxMyeh0sdrt3AYuaXbauGicW71M/field_definitions/zFEova6LiPM/codes?about=1",
"href" : "https://www.someserver.com/form_definitions/OIlG4GxMyeh0sdrt3AYuaXbauGicW71M/field_definitions/zFEova6LiPM/codes",
"method" : "GET",
"rel" : "self",
"title" : null,
"type" : "codes"
},
{
"href" : "https://www.someserver.com/form_definitions/OIlG4GxMyeh0sdrt3AYuaXbauGicW71M/field_definitions/zFEova6LiPM/codes",
"method" : "POST",
"rel" : "codes",
"title" : "create new codes entity"
}
],
"meta" : {
"description" : null,
"last_page" : 1,
"page_offset" : 0,
"page_size" : 50,
"query-template" : "/codes{?query_search,page_offset,page_size,query_identification,embedded,properties,about}",
"total" : 6
}
}
As I unterstood I need three classes: e.g. codes, links and meta.
I created a class "clscodes":
Public Class clsCode
Private m_href As String
Private m_rel As String
Private m_title As String
Public Property Href As String
Get
Return m_href
End Get
Set(value As String)
m_href = value
End Set
End Property
Public Property Rel As String
Get
Return m_rel
End Get
Set(value As String)
m_rel = value
End Set
End Property
Public Property Title As String
Get
Return m_title
End Get
Set(value As String)
m_title = value
End Set
End Property
End Class
And I created a class clsValuelist:
Public Class clsWerteliste
Private m_code As IList(Of clsCode)
Public Property Code() As clsCode()
Get
Return m_code
End Get
Set(value As clsCode())
m_code = value
End Set
End Property
End Class
When I try to deserialize it I get "nothing" as in "CoolOutput"
Dim CoolOutput As New clsWerteliste
CoolOutput = JsonConvert.DeserializeObject(Of clsWerteliste)(jsonstring)
Your classes are pretty close, it looks like you possibly tried to pretty things up a bit such as changing codes to Codes but in so doing the properties no longer match. You can change class names but not property names (at least not that way):
Public Class CodeLinkContainer
<JsonProperty("codes")>
Public Property Codes As IList(Of Code)
<JsonProperty("links")>
Public Property Links As IList(Of Link)
<JsonProperty("meta")>
Public Property Meta As Meta
End Class
Public Class Meta
Public Property description As Object
Public Property last_page As Integer
Public Property page_offset As Integer
Public Property page_size As Integer
Public Property querytemplate As String
Public Property total As Integer
End Class
Public Class Code
Public Property href As String
Public Property rel As String
Public Property title As String
End Class
Public Class Link
Public Property about As String
Public Property href As String
Public Property method As String
Public Property rel As String
Public Property title As String
Public Property type As String
End Class
Using AutoImplement properties, available for some time now, means you can skip all the Get, Set boilerplate code. VS will create the classes for you also:
Edit Menu -> Paste Special -> Paste Json As Classes
You sometimes have to tweak the class if there is an array/list property. For instance, the robots may write:
Public Property elements() As Element
When it should be:
Public Property elements As Element()
The container class shows how to use <JsonProperty("pname")> to change the property name if you wish. This often needs to be done to create an alias for a property name which is a key word in VB (Return, Error etc). In this case, I changed codes and links to be Lists as you did.
Dim jstr = ... from whereever
Dim CodeLinks = JsonConvert.DeserializeObject(Of CodeLinkContainer)(jstr)
Console.WriteLine(CodeLinks.meta.total)
For Each Item In CodeLinks.codes
Console.WriteLine(Item.title)
Next
Result:
6
TITLE 1
TITLE 2
TITLE 3

Organizing a JSON into some text boxes in VB.net [duplicate]

I am very new to json, JSON.net and all that. After reading similiar questions here I cannot get my code working.
What exactly is my error? What have I overseen?
Is it possible to skip the classes "links" and "meta" for testing purposes or do I have to define EVERY property?
I have got the following REST output:
{
"codes" : [
{
"href" : "https://www.someserver.com/form_definitions/OIlG4GxMyeh0sdrt3AYuaXbauGicW71M/field_definitions/zFEova6LiPM/codes/4Sxnr961xzM",
"rel" : "document_field_definition_code",
"title" : "TITLE 1"
},
{
"href" : "https://www.someserver.com/form_definitions/OIlG4GxMyeh0sdrt3AYuaXbauGicW71M/field_definitions/zFEova6LiPM/codes/buho0CsLc5k",
"rel" : "document_field_definition_code",
"title" : "TITLE 2"
},
{
"href" : "https://www.someserver.com/form_definitions/OIlG4GxMyeh0sdrt3AYuaXbauGicW71M/field_definitions/zFEova6LiPM/codes/RvQoykUM_Sk",
"rel" : "document_field_definition_code",
"title" : "TITLE 3"
}
],
"links" : [
{
"about" : "https://www.someserver.com/form_definitions/OIlG4GxMyeh0sdrt3AYuaXbauGicW71M/field_definitions/zFEova6LiPM/codes?about=1",
"href" : "https://www.someserver.com/form_definitions/OIlG4GxMyeh0sdrt3AYuaXbauGicW71M/field_definitions/zFEova6LiPM/codes",
"method" : "GET",
"rel" : "self",
"title" : null,
"type" : "codes"
},
{
"href" : "https://www.someserver.com/form_definitions/OIlG4GxMyeh0sdrt3AYuaXbauGicW71M/field_definitions/zFEova6LiPM/codes",
"method" : "POST",
"rel" : "codes",
"title" : "create new codes entity"
}
],
"meta" : {
"description" : null,
"last_page" : 1,
"page_offset" : 0,
"page_size" : 50,
"query-template" : "/codes{?query_search,page_offset,page_size,query_identification,embedded,properties,about}",
"total" : 6
}
}
As I unterstood I need three classes: e.g. codes, links and meta.
I created a class "clscodes":
Public Class clsCode
Private m_href As String
Private m_rel As String
Private m_title As String
Public Property Href As String
Get
Return m_href
End Get
Set(value As String)
m_href = value
End Set
End Property
Public Property Rel As String
Get
Return m_rel
End Get
Set(value As String)
m_rel = value
End Set
End Property
Public Property Title As String
Get
Return m_title
End Get
Set(value As String)
m_title = value
End Set
End Property
End Class
And I created a class clsValuelist:
Public Class clsWerteliste
Private m_code As IList(Of clsCode)
Public Property Code() As clsCode()
Get
Return m_code
End Get
Set(value As clsCode())
m_code = value
End Set
End Property
End Class
When I try to deserialize it I get "nothing" as in "CoolOutput"
Dim CoolOutput As New clsWerteliste
CoolOutput = JsonConvert.DeserializeObject(Of clsWerteliste)(jsonstring)
Your classes are pretty close, it looks like you possibly tried to pretty things up a bit such as changing codes to Codes but in so doing the properties no longer match. You can change class names but not property names (at least not that way):
Public Class CodeLinkContainer
<JsonProperty("codes")>
Public Property Codes As IList(Of Code)
<JsonProperty("links")>
Public Property Links As IList(Of Link)
<JsonProperty("meta")>
Public Property Meta As Meta
End Class
Public Class Meta
Public Property description As Object
Public Property last_page As Integer
Public Property page_offset As Integer
Public Property page_size As Integer
Public Property querytemplate As String
Public Property total As Integer
End Class
Public Class Code
Public Property href As String
Public Property rel As String
Public Property title As String
End Class
Public Class Link
Public Property about As String
Public Property href As String
Public Property method As String
Public Property rel As String
Public Property title As String
Public Property type As String
End Class
Using AutoImplement properties, available for some time now, means you can skip all the Get, Set boilerplate code. VS will create the classes for you also:
Edit Menu -> Paste Special -> Paste Json As Classes
You sometimes have to tweak the class if there is an array/list property. For instance, the robots may write:
Public Property elements() As Element
When it should be:
Public Property elements As Element()
The container class shows how to use <JsonProperty("pname")> to change the property name if you wish. This often needs to be done to create an alias for a property name which is a key word in VB (Return, Error etc). In this case, I changed codes and links to be Lists as you did.
Dim jstr = ... from whereever
Dim CodeLinks = JsonConvert.DeserializeObject(Of CodeLinkContainer)(jstr)
Console.WriteLine(CodeLinks.meta.total)
For Each Item In CodeLinks.codes
Console.WriteLine(Item.title)
Next
Result:
6
TITLE 1
TITLE 2
TITLE 3

Strange Mapping Behaviour Jackson JSON

I've got a strange mapping Issue with Jackson on Android.
I've got a "Content" Class which should be used by the Jackson Mapper.
It looks like this:
public class content {
private String header;
private String subheader;
private String bodytext;
#JsonProperty("singleimage")
private String image;
#JsonProperty("uid")
private String id;
#JsonProperty("link")
private String article;
#JsonProperty("CType")
private String cType;
// Eclipse auto generated getters & setters
...
}
The corresponding JSON Object looks like this:
{
"header": "xyz",
"subheader": "abc",
"bodytext": "abc",
"singleimage": "abc",
"images": "abc.jpg",
"teaser_elements": "",
"uid": "13",
"link": "xyz.htm",
"CType": "row_header"
}
Now when I use the Jackson Maper to create instances of Content from a provided JSON all fields of the content class get populated correctly - all except "cType".
I already tried to move the #JsonProperty("CType") annotation to the setCType Method but still no effect.
I don't get any Exceptions while mapping the class or anything else and as it seems to me that all mappings pretty much do the same (mapping to String) im kinda buffled why it doesn't work wit the "CType".
Any suggestions what the problem might be are highly appreciated.