DataContractJsonSerializer include object name in JSON object - json

I'm trying to serialize a JSON object so I can send it to a web service. I'm using this asp.net vb code:
Dim ser As DataContractJsonSerializer = New DataContractJsonSerializer(postData.GetType())
Dim MS As MemoryStream = New MemoryStream()
ser.WriteObject(MS, postData)
json = Encoding.UTF8.GetString(MS.ToArray())
which produces this JSON:
{"guid":"10049cf5-a622-4aa6-a1d5-58022c4e2a19"}
But what I NEED...is this JSON:
{"registerRequest": {"guid":"10049cf5-a622-4aa6-a1d5-58022c4e2a19"}}
here is the class definition for the object I'm trying to send:
Partial Public Class registerRequest
Private Property _guid As String
Public Property guid As String
Get
Return _guid
End Get
Set(value As String)
_guid = value
End Set
End Property
Sub New()
End Sub
End Class
How do I get the name of the class to appear in the JSON object as described above?

Add datacontractjsonserializersettings to your constructor on DataContractDataSerializer
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.json.datacontractjsonserializersettings.emittypeinformation.aspx
Try using rootname setting in the constructor instead.
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.json.datacontractjsonserializersettings.rootname.aspx

OK, to match the format I Just created a wrapper class with a "registerRequest" object inside of it. Kind of a work around, but it works!
Partial Public Class SerializedRegisterRequest
Private Property _registerRequest As registerRequest
Public Property registerRequest As registerRequest
Get
Return _registerRequest
End Get
Set(value As registerRequest)
_registerRequest = value
End Set
End Property
Sub New()
End Sub
End Class
Partial Public Class registerRequest
Private Property _guid As String
Public Property guid As String
Get
Return _guid
End Get
Set(value As String)
_guid = value
End Set
End Property
Sub New()
End Sub
End Class

Related

'The node must be of type 'JsonObject'.'

I'm trying to parse this Json
With the code:
Dim streamData As Stream = Nothing
Using http As New HttpClient
Dim url As String = "https://api.hotbit.io/api/v1/market.deals?market=KIBA/USDT&limit=150&last_id=1521100930&api_key=44812d8f-66d3-01c0-94c3b29305040b03&sign=98EEC3D69D3F70F9BDFED901984B2AA4"
Dim t As Task(Of Stream) = http.GetStreamAsync(url)
streamData = t.Result
End Using
Dim jsonResponse As JsonNode = JsonNode.Parse(streamData)
Dim result As JsonObject = jsonResponse("result").AsObject
Dim c As String = String.Empty
For Each kvp In result.AsEnumerable
c &= kvp.Value("price").ToString & vbCr
Next
RichTextBox1.Text = c
End Sub
but I keep getting the error at debug
The node must be of type 'JsonObject'.'
on the line
Dim result As JsonObject = jsonResponse("result").AsObject
How it comes it gives an error If I'm already trying to parse it as a Jsonobject?
Thanks
Give a go at this..
Paste this into a new class file:
Namespace HotBit
Partial Public Class TradeCollection
<JsonProperty("error")>
Public Property [Error] As Object
<JsonProperty("result")>
Public Property Result As List(Of Result)
<JsonProperty("id")>
Public Property Id As Long
End Class
Partial Public Class Result
<JsonProperty("id")>
Public Property Id As Long
<JsonProperty("time")>
Public Property Time As Long
<JsonProperty("price")>
Public Property Price As String
<JsonProperty("amount")>
<JsonConverter(GetType(ParseStringConverter))>
Public Property Amount As Long
<JsonProperty("type")>
Public Property Type As TypeEnum
End Class
Public Enum TypeEnum
Buy
Sell
End Enum
Partial Public Class TradeCollection
Public Shared Function FromJson(ByVal json As String) As TradeCollection
Return JsonConvert.DeserializeObject(Of TradeCollection)(json, Settings)
End Function
End Class
Public Module Serialize
<Extension()>
Public Function ToJson(ByVal self As TradeCollection) As String
Return JsonConvert.SerializeObject(self, Settings)
End Function
End Module
Friend Module Converter
Public ReadOnly Settings As JsonSerializerSettings = New JsonSerializerSettings With {
.MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
.DateParseHandling = DateParseHandling.None
}
End Module
Friend Class ParseStringConverter
Inherits JsonConverter
Public Overrides Function CanConvert(ByVal t As Type) As Boolean
Return t Is GetType(Long) OrElse t Is GetType(Long?)
End Function
Public Overrides Function ReadJson(ByVal reader As JsonReader, ByVal t As Type, ByVal existingValue As Object, ByVal serializer As JsonSerializer) As Object
If reader.TokenType = JsonToken.Null Then Return Nothing
Dim value = serializer.Deserialize(Of String)(reader)
Dim l As Long
If Long.TryParse(value, l) Then
Return l
End If
Throw New Exception("Cannot unmarshal type long")
End Function
Public Overrides Sub WriteJson(ByVal writer As JsonWriter, ByVal untypedValue As Object, ByVal serializer As JsonSerializer)
If untypedValue Is Nothing Then
serializer.Serialize(writer, Nothing)
Return
End If
Dim value = CLng(untypedValue)
serializer.Serialize(writer, value.ToString())
Return
End Sub
Public Shared ReadOnly Singleton As ParseStringConverter = New ParseStringConverter()
End Class
Friend Class TypeEnumConverter
Inherits JsonConverter
Public Overrides Function CanConvert(ByVal t As Type) As Boolean
Return t Is GetType(TypeEnum) OrElse t Is GetType(TypeEnum?)
End Function
Public Overrides Function ReadJson(ByVal reader As JsonReader, ByVal t As Type, ByVal existingValue As Object, ByVal serializer As JsonSerializer) As Object
If reader.TokenType = JsonToken.Null Then Return Nothing
Dim value = serializer.Deserialize(Of String)(reader)
Select Case value
Case "buy"
Return TypeEnum.Buy
Case "sell"
Return TypeEnum.Sell
End Select
Throw New Exception("Cannot unmarshal type TypeEnum")
End Function
Public Overrides Sub WriteJson(ByVal writer As JsonWriter, ByVal untypedValue As Object, ByVal serializer As JsonSerializer)
If untypedValue Is Nothing Then
serializer.Serialize(writer, Nothing)
Return
End If
Dim value = CType(untypedValue, TypeEnum)
Select Case value
Case TypeEnum.Buy
serializer.Serialize(writer, "buy")
Return
Case TypeEnum.Sell
serializer.Serialize(writer, "sell")
Return
End Select
Throw New Exception("Cannot marshal type TypeEnum")
End Sub
Public Shared ReadOnly Singleton As TypeEnumConverter = New TypeEnumConverter()
End Class
End Namespace
Then install Newtonsoft (if not already) and Imports it
Then Imports HotBit (or if you changed the Namespace of the "paste this" above, Imports that new namespace
Then do your request and query the result e.g.:
Sub Main(args As String())
Dim s = New WebClient().DownloadString("https://api.hotbit.io/api/v1/market.deals?market=KIBA/USDT&limit=150&last_id=1521100930&api_key=44812d8f-66d3-01c0-94c3b29305040b03&sign=98EEC3D69D3F70F9BDFED901984B2AA4")
Dim tc = TradeCollection.FromJson(s)
Dim prices = String.Join(","c, tc.Result.Select(Function(r) r.Price))
End Sub

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

Newtonsoft JSON parsing into object

My VB is a bit rusty but I need to parse a JSON string. I did it already in C# where I didn't have an issue. This is an old project and I'm using VS2008 for it.
This is my class:
Public Class ResponseMeta
Private _type As String
<JsonProperty("type")> _
Public Property type() As String
Get
Return _type.ToString()
End Get
Set(ByVal value As String)
_type = value
End Set
End Property
Private _message As String
<JsonProperty("message")> _
Public Property message() As String
Get
Return _message
End Get
Set(ByVal value As String)
_message = value
End Set
End Property
Private _message_v1 As String
<JsonProperty("message-v1")> _
Public Property message_v1() As String
Get
Return _message_v1
End Get
Set(ByVal value As String)
_message_v1 = value
End Set
End Property
Private _message_v2 As String
<JsonProperty("message-v2")> _
Public Property message_v2() As String
Get
Return _message_v2
End Get
Set(ByVal value As String)
_message_v2 = value
End Set
End Property
Private _message_v3 As String
<JsonProperty("message-v3")> _
Public Property message_v3() As String
Get
Return _message_v3
End Get
Set(ByVal value As String)
_message_v3 = value
End Set
End Property
Private _message_v4 As String
<JsonProperty("message-v4")> _
Public Property message_v4() As String
Get
Return _message_v4
End Get
Set(ByVal value As String)
_message_v4 = value
End Set
End Property
End Class
The code to deserialize is:
Dim test As String
test = "{""response-meta"":{""type"":""S"",""message"":"""",""Total No Of Records"":"""",""message-v1"":""1"",""message-v2"":"""",""message-v3"":"""",""message-v4"":""""}}"
Dim testcl As ResponseMeta
testcl = JsonConvert.DeserializeObject(Of ResponseMeta)(test)
All properties of the object are set to Nothing and if I add watch, it says:
type = {"Object reference not set to an instance of an object."}
I have now spent countless hours on this and Google doesn't found a hint or a clue of what might be getting wrong here.
Any suggestions are very welcome.
The JSON does not match up to what you are trying to parse it to.
You are missing a root object.
Public Class RootObject
Private _root As ResponseMeta
<JsonProperty("response-meta")> _
Public Property ResponseMeta() As ResponseMeta
Get
Return _root
End Get
Set(ByVal value As ResponseMeta)
_root = value
End Set
End Property
End Class
So based on the JSON you would need to deserialize to root object first then get the meta data
Dim root As RootObject = JsonConvert.DeserializeObject(Of RootObject)(test)
Dim testcl As ResponseMeta = root.ResponseMeta

JSon Serialize complex object with datatable inside

I have this kind of object:
Public Class ClasseProva
Inherits RM_Base
Public Sub New()
Me.NomeTabella = "ClasseProva"
End Sub
Private m_AZI_ID As Integer
Public Property AZI_ID() As Integer
Get
Return m_AZI_ID
End Get
Set(ByVal value As Integer)
m_AZI_ID = value
End Set
End Property
Private m_dtPROGETTI As DataTable
Public Function ProgettiRO() As DataTable
Return m_dtPROGETTI
End Function
Public Sub ProgettiWO(value As DataTable)
m_dtPROGETTI = value
End Sub
End Class
So if in my object there is no datatable, I know how to serialize using Json and use serialized object as cookie. So in this way I have
public ClasseProva CookieClasseProva
{
get
{
try
{
string myObjectJson = Request.Cookies["CookieClasseProva"].Value;
return JsonConvert.DeserializeObject<ClasseProva>(myObjectJson);
}
catch { return null; }
}
set
{
string myObjectJson = JsonConvert.SerializeObject(value);
var cookie = new HttpCookie("CookieClasseProva", myObjectJson)
{
Expires = DateTime.Now.AddYears(1)
};
Response.Cookies.Add(cookie);
}
}
But after I added datatable, serialization function doesn't serialize datatable.
EDIT:
I don't know how attach a project. But now I'm copying Class of my BL project
Public Class Class1
Private m_intValue As Integer
Public Property MyIntValue() As Integer
Get
Return m_intValue
End Get
Set(ByVal value As Integer)
m_intValue = value
End Set
End Property
Private m_dtValue As DataTable
Public Property MyDatatable() As DataTable
Get
Return m_dtValue
End Get
Set(value As DataTable)
m_dtValue = value
End Set
End Property
End Class
and code section of a simple page
Imports Newtonsoft.Json
Imports DatatableSerializationBL
Public Class _Default
Inherits Page
Public Property CookieUtente() As Class1
Get
Try
Dim myObjectJson As String = Request.Cookies("CookieUtente").Value
Return JsonConvert.DeserializeObject(Of Class1)(myObjectJson)
Catch
Return Nothing
End Try
End Get
Set(value As Class1)
Dim myObjectJson As String = JsonConvert.SerializeObject(value)
Dim cookie = New HttpCookie("CookieUtente", myObjectJson)
Response.Cookies.Add(cookie)
End Set
End Property
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
Dim c As New Class1
c.MyIntValue = 1
c.MyDatatable = New DataTable
c.MyDatatable.NewRow()
CookieUtente = c
Console.WriteLine(CookieUtente.MyDatatable.Rows.Count)
End Sub
End Class
So in the design page , I print rows.count value and it prints 0
ROWS : <%= CookieUtente.MyDatatable.Rows.Count%>

How to return two objects (including one list) in JSON with WCF

I am trying to resolve my issue.
This is my Service Contract (IService1.vb)
<OperationContract()> _
<WebInvoke(Method:="GET", BodyStyle:=WebMessageBodyStyle.Wrapped, ResponseFormat:=WebMessageFormat.Json, UriTemplate:="/GetBooks")> _
Function GetBooks() As List(Of Book)
<DataContract()> _
Class Book
Public Property bookchapter() As List(Of Chapter)
Get
Return m_bookchapter
End Get
Set(value As List(Of Chapter))
m_bookchapter = value
End Set
End Property
Private m_bookchapter As List(Of Chapter)
Public Property success() As Integer
Get
Return m_success
End Get
Set(value As Integer)
m_success = value
End Set
End Property
Private m_success As Integer
End Class
<DataContract()> _
Class Chapter
Public Property description() As String
Get
Return m_description
End Get
Set(value As String)
m_description = value
End Set
End Property
Private m_description As String
End Class
This is my Service (Service1.vb)
Public Function GetBooks() As List(Of IGPService.Book) Implements IGPService.GetBooks
Dim books As New List(Of IGPService.Book)
Dim newBook As IGPService.Book = New IGPService.Book
For i As Integer = 0 To 3
Dim newchapter As IGPService.Chapter = New IGPService.Chapter
newchapter.description = "Chapter1"
newBook.bookchapter.Add(newchapter)
Next
newBook.success = 1
books.Add(newBook)
Return books
End Function
When I call GetBooks, I get the following error:
The server encountered an error processing the request. See server
logs for more details.
I don't know what is wrong here. I couldn't find anything in the Windows EventLog.
I added a New() Contructor to the Book Class and now it works. But i don't know why!
Class Book
Public Property bookchapter() As List(Of Chapter)
Get
Return m_bookchapter
End Get
Set(value As List(Of Chapter))
m_bookchapter = value
End Set
End Property
Private m_bookchapter As List(Of Chapter)
Public Property success() As Integer
Get
Return m_success
End Get
Set(value As Integer)
m_success = value
End Set
End Property
Private m_success As Integer
**Public Sub New()
bookchapter = New List(Of Chapter)
End Sub**
End Class
I want to understand why this is. Can somebody explain me the difference with and without New()!