how to deserialize this json on vb.net? - arrays

i have this data in json format:
{
"status":{
"timestamp":"2021-01-07T17:13:48.471Z",
"error_code":0,
"error_message":null,
"elapsed":12,
"credit_count":1,
"notice":null,
"total_count":4115
},
"data":[
{
"id":1,
"name":"Bitcoin",
"symbol":"BTC",
"slug":"bitcoin",
"num_market_pairs":9732,
"date_added":"2013-04-28T00:00:00.000Z",
"tags":[
"mineable",
"pow",
"sha-256",
"store-of-value",
"state-channels"
],
"max_supply":21000000,
"circulating_supply":18593700,
"total_supply":18593700,
"platform":null,
"cmc_rank":1,
"last_updated":"2021-01-07T17:12:02.000Z",
"quote":{
"USD":{
"price":39362.167971369854,
"volume_24h":78135138852.86674,
"percent_change_1h":2.61231359,
"percent_change_24h":12.47756102,
"percent_change_7d":36.98956944,
"market_cap":731888342609.2596,
"last_updated":"2021-01-07T17:12:02.000Z"
}
}
},
{
"id":1027,
"name":"Ethereum",
"symbol":"ETH",
"slug":"ethereum",
"num_market_pairs":5934,
"date_added":"2015-08-07T00:00:00.000Z",
"tags":[
"mineable",
"pow",
"smart-contracts"
],
"max_supply":null,
"circulating_supply":114155463.749,
"total_supply":114155463.749,
"platform":null,
"cmc_rank":2,
"last_updated":"2021-01-07T17:12:02.000Z",
"quote":{
"USD":{
"price":1261.606649005652,
"volume_24h":39345516218.36576,
"percent_change_1h":3.1558102,
"percent_change_24h":7.80752209,
"percent_change_7d":71.81090319,
"market_cap":144019292086.06207,
"last_updated":"2021-01-07T17:12:02.000Z"
}
}
}
]
}
and, in vb.net, with special paste i got this definition:
Public Class Rootobject
Public Property status As Status
Public Property data() As Datum
End Class
Public Class Status
Public Property timestamp As Date
Public Property error_code As Integer
Public Property error_message As Object
Public Property elapsed As Integer
Public Property credit_count As Integer
Public Property notice As Object
Public Property total_count As Integer
End Class
Public Class Datum
Public Property id As Integer
Public Property name As String
Public Property symbol As String
Public Property slug As String
Public Property num_market_pairs As Integer
Public Property date_added As Date
Public Property tags() As String
Public Property max_supply As Integer
Public Property circulating_supply As Integer
Public Property total_supply As Integer
Public Property platform As Object
Public Property cmc_rank As Integer
Public Property last_updated As Date
Public Property quote As Quote
End Class
Public Class Quote
Public Property USD As USD
End Class
Public Class USD
Public Property price As Single
Public Property volume_24h As Single
Public Property percent_change_1h As Single
Public Property percent_change_24h As Single
Public Property percent_change_7d As Single
Public Property market_cap As Single
Public Property last_updated As Date
End Class
but when i try with this command to deserialize
Dim m As IEnumerable(Of Rootobject) =
JsonConvert.DeserializeObject(Of IEnumerable(Of Rootobject))(res)
i get this error:
Newtonsoft.Json.JsonSerializationException: 'Cannot deserialize the current JSON object
(e.g. {"name":"value"}) into type
'System.Collections.Generic.IEnumerable`1[CoinMarketCap.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 'status', line 1, position 10.'
im stucked... any idea?
Thanks in advance.

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.
In other words, change
Dim m As IEnumerable(Of Rootobject) = JsonConvert.DeserializeObject(Of IEnumerable(Of Rootobject))(res)
to
Dim m As Rootobject = JsonConvert.DeserializeObject(Of Rootobject)(res)

Related

Deserialize complex JSON with Newtonsoft.Json - Visual Basic

Need help to deserialize complex json file using Visual Basic and Newtonsoft.Json library.
Here is the sample of Json file:
{
"value": [
{
"Id": 12345,
"Name": "Test",
"CardCount": 0,
"DailySpendLimit": 0.00,
"WeeklySpendLimit": 50.00,
"MonthlySpendLimit": 100.00,
"YearlySpendLimit": 1000.00,
"LifetimeSpendLimit": 0.00,
"MerchantCategories": [
"#{Id=11111; Name=Associations \u0026 Organizations; Description=Post Office, local and federal government services, religious organizations.; TransactionLimit=0.00; DailySpendLimit=0.00; WeeklySpendLimit=0.00; MonthlySpendLimit=0.00; YearlySpendLimit=0.00; LifetimeSpendLimit=0.00}",
"#{Id=22222; Name=Automotive Dealers; Description=Vehicle dealerships (car, RV, motorcycle, boat, recreational).; TransactionLimit=0.00; DailySpendLimit=0.00; WeeklySpendLimit=0.00; MonthlySpendLimit=0.00; YearlySpendLimit=0.00; LifetimeSpendLimit=0.00}"
]
}
],
"Count": 1
}
I had setup classes:
Public Class TEST_AdvRules
<JsonProperty("value")>
Public Property ValueDetails As ValueList()
Public Class ValueList
<JsonProperty("Id")>
Public Property RuleId As Integer
<JsonProperty("Name")>
Public Property RuleName As String = ""
Public Property CardCount As Integer
Public Property DailySpendLimit As Double
Public Property WeeklySpendLimit As Double
Public Property MonthlySpendLimit As Double
Public Property YearlySpendLimit As Double
Public Property LifetimeSpendLimit As Double
<JsonProperty("MerchantCategories")>
Public Property MerchantCategories() As List(Of MerchantCategoriesList)
End Class
Public Class MerchantCategoriesList
Public Property Id As Integer
Public Property Name As String = ""
Public Property Description As String = ""
Public Property TransactionLimit As Double
Public Property DailySpendLimit As Double
Public Property WeeklySpendLimit As Double
Public Property MonthlySpendLimit As Double
Public Property YearlySpendLimit As Double
Public Property LifetimeSpendLimit As Double
End Class
End Class
The code for deserilization:
Dim jsonStringP = IO.File.ReadAllText(PathJson & SecFileName)
Dim serSettings = New JsonSerializerSettings()
serSettings.ContractResolver = New CamelCasePropertyNamesContractResolver()
Dim RulesPEX = JsonConvert.DeserializeObject(Of TEST_AdvRules)(jsonStringP, serSettings)
But it errors out on the deserialization line - can't convert MerchantCategories.
I have never dealt with Json with [ "# array sequence. Am I processing it wrong?
Also - there is a character sequence '\u0026 ' within Merchant categories. Does it require special handling? Thank you!
The problem is that MerchantCategories is a string collection. You will have to convert each string to object using a custom string analyzer. Last time I worked with Vb.net was more then 10 years ago, so I can give you a solution in C# , your part would be to convert it to VB.Net. I don't feel like installing VB.NET compilliar at my mashine.
using Newtonsoft.Json;
var jsonObject = JObject.Parse(jsonStringP);
var jsonArr=new JArray();
foreach (var item in (JArray) jsonObject["value"][0]["MerchantCategories"])
{
jsonArr.Add(ConvertToJObject(item.ToString()));
}
jsonObject["value"][0]["MerchantCategories"]=jsonArr;
TEST_AdvRules RulesPEX = jsonObject.ToObject<TEST_AdvRules>();
this function converts a string to a JObject
public JObject ConvertToJObject(string str)
{
var strStart=str.IndexOf("{")+1;
var strEnd=str.IndexOf("}")-2;
var arr = str.Substring(strStart, strEnd).Split(";").Select(c => c.Split("="));
var jObj = new JObject();
foreach (var item in arr)
jObj.Add(new JProperty(item[0].Trim(), item[1].Trim()));
return jObj;
}
let Visual Studio create the class for you:
copy the whole json file content to the clipboard
in VS, add a new empty class -> Edit -> Paste Special -> paste json as class
I tend to add a shared Read-Method for easier construction.
Of course you can rename your classes as you wish :-)
I'm on german VS but you get the idea :-)
Translating Serge's answer into VB (note untested code so it's possible there are some minor errors)...
Imports Newtonsoft.Json
'...
Dim jsonObject = JObject.Parse(jsonStringP)
Dim jsonArr = new JArray()
For Each item In CType(jsonObject("value")(0)("MerchantCategories"), JArray)
jsonArr.Add(ConvertToJObject(item.ToString()))
Next
jsonObject("value")(0)("MerchantCategories") = jsonArr
Dim RulesPEX As TEST_AdvRules = jsonObject.ToObject(Of TEST_AdvRules)()
and
Public Function ConvertToJOBject(ByVal str As String) As JObject
Dim strStart = str.IndexOf("{") + 1
Dim strEnd = str.IndexOf("}") - 2
Dim arr = str.Substring(strStart, strEnd).Split(";").Select(Function(c) c.Split("="))
Dim jObj = New JObject()
For Each item In arr
jObj.Add(New JProperty(item(0).Trim(), item(1).Trim()))
Next
Return jObj
End Function

Writing parquet output with selected attributes from Bean

I have a bean class
#Getter
#Setter
public class Employee {
String id;
String name;
String depart;
String address;
final String pipe= "|";
#Override
public String toString() {
return id +pipe+ name +pipe+depart;
}
}
And I have a JavaRDD<Employee> emprdd;
and when I do the emprdd.saveAsText(path);. I get the output as based on the toString method.
Now I wanted to write into the parquet format after converting it to the dataframe but I need only (id,name,depart). I tried sqlContext.createDataframe(rdd,Employee.class); (syntax ignored), but I dont need all the properties.
Can anyone guide me through this. (This is a sample , I have bean class with 350+ attributes)

Automate the creation of converters or other generic solution

When i need to display an enumeration in a View, i write a converter for this type of enumeration
For Example:
Public Enum ReportTypes
Overview
Crosstable
AllCPDetails
End Enum
My converter is:
Public Class ReportTypeToStringConverter
Implements IValueConverter
Public Property Overview As String
Public Property Crosstable As String
Public Property AllCPDetails As String
Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
Dim enumValue As ReportTypes = DirectCast(value, ReportTypes)
Select Case enumValue
Case ReportTypes.Overview
Return Overview
Case ReportTypes.Crosstable
Return Crosstable
Case ReportTypes.AllCPDetails
Return AllCPDetails
Case Else
Return DependencyProperty.UnsetValue
End Select
End Function
Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
Throw New NotImplementedException()
End Function
End Class
then, in my XAML i can write this:
<local:ReportTypeToStringConverter x:Key="ReportTypeToStringConverter"
Overview="Overview"
Crosstable="Cross Table"
AllCPDetails="All CP Details"/>
In this example there is an relationship of "Enum <--> String", but i can need write another relationships: "Enum <--> Color", "Enum <--> Visibility"....
The code is very clean and all work ok, but when i have many enums, or many relationships... How can i automatice the converter creation? Snippets? Item Template in Visual Studio?
Another generic solution?
The probably most generic converter could use a ResourceDictionary to map from the a value's ToString() result to an arbitrary object. The source value does not even need to be an enum.
public class GenericConverter : IValueConverter
{
private readonly ResourceDictionary resources = new ResourceDictionary();
public ResourceDictionary Resources
{
get { return resources; }
}
public object Convert(
object value, Type targetType, object parameter, CultureInfo culture)
{
return resources[value.ToString()];
}
public object ConvertBack(
object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
You would e.g. use it like this to convert Visibility values:
<Window.Resources>
<local:GenericConverter x:Key="VisibilityToSomeStringConverter">
<local:GenericConverter.Resources>
<sys:String x:Key="Visible">VISIBLE</sys:String>
<sys:String x:Key="Hidden">HIDDEN</sys:String>
<sys:String x:Key="Collapsed">COLLAPSED</sys:String>
</local:GenericConverter.Resources>
</local:GenericConverter>
<local:GenericConverter x:Key="VisibilityToSomeIntConverter">
<local:GenericConverter.Resources>
<sys:Int32 x:Key="Visible">10</sys:Int32>
<sys:Int32 x:Key="Hidden">20</sys:Int32>
<sys:Int32 x:Key="Collapsed">30</sys:Int32>
</local:GenericConverter.Resources>
</local:GenericConverter>
</Window.Resources>

et Return the Whole Subdocument Arrary from MongoDB

I need to get all of the subdocuments array from the Courses Class where the User.UserId = whatever and Courses.Status=active
Public Class User
Public Property UserId As String 'this is unique so i would like to index this, unless you think otherwise
Public Property CourseData() As List(Of Courses) '
Public Property Groups As List(Of String)
Public Property BU As List(Of String)
End Class
Public Class Courses
Public Property id As String 'this can be dynamic
Public Property description As String
Public Property CompletionDate As String
Public Property Hours As String
Public Property Status As String
End Class
Using vb.net , I tried a few ways, I only want the courses returned that have a Status="Active" to be dumped into Ienumberable
I tried (_users is a collection of User) (_uid is a variable passed into it)
Return _users.FindAs(Of User)(Query.And(query.EQ("LearningHours.Status", "Active"), (Query.EQ("UserId", _uid))))
Return _users.FindAs(Of User)(Query.And(query.EQ("LearningHours.Status", "Active"), (Query.EQ("UserId", _uid)))).SetFields("Courses", "1")
Return _users.FindAs(Of Courses)(Query.And(query.EQ("LearningHours.Status", "Active"), (Query.EQ("UserId", _uid))))
Return _users.FindAs(Of Courses)(Query.And(query.EQ("LearningHours.Status", "Active"), (Query.EQ("UserId", _uid)))).SetFields("Courses", "1")
None seem to work, they usually come back with the fields from Class User or both Class User and Class Course, but the Course fields are blank
I even am trying linq.. this works - but only returns 1 row result
Dim uc = From _u In _users.AsQueryable(Of User)()
Where _u.userid = _userid _
Select _
CourseID = _u.Courses.Where(Function(c) c.State = "Submitted").Select(Function(c) c.CourseId)(0), _
CourseDescription = _u.Courses.Where(Function(c) c.State = "Submitted").Select(Function(c) c.CourseDescription)(0)
Seems easy enough to do, just cant get it
Got It, I think I was over thinking it
Once I declare an instance of the class, I can iterate through the subdocument
Dim _u as new User
For Each c In _user.Courses.Where(Function(cs) cs.Status= "Active").Select(Function(cs) cs)
console.writeline(c.id & c.description & "so on...")
Next

parsing by Linq to JSON

I was trying to parse this using System.Json but I'm a bit confused how to use LINQ on this. The JSON string returned was something like:
{"SearchResults":[{"PageCount":"1"},
{"SEARCHVAL":"Result","CATEGORY":"Category1","X":"1","Y":"2"},
{"SEARCHVAL":"AnotherResult","CATEGORY":"Category1","X":"2","Y":"2"}]}
My code starts out as:
WebClient client = new WebClient();
client.OpenReadCompleted +=
new OpenReadCompletedEventHandler(client_OpenReadCompleted);
client.OpenReadAsync(uri);
then proceeds to the event handler where the result is stored in a Stream. Any example how to get just the SEARCHVALs, CATEGORYs, Xs and Ys from the stream using LINQ?
The DataContractJSonSerializer is one way to do it but the presence of the "PageCount" object makes its use awkard. It looks to me as though someone has goofed on the server end, it would make much more sense to have the page count a property of the outer object and therefore leave the search results array to contain an homogeneous set of objects.
The System.Json namespace is handy for this sort of JSON since its very flexible.
JsonObject searchResults = (JsonObject)JsonValue.Load(e.Result);
Now you could use some Linq to get a set of objects out of this but first so we need to create a DTO type for it:-
public class SearchResult
{
public string SearchValue {get; set;}
public string Category {get; set;}
public string X {get; set;}
public string Y {get; set;}
}
So now the results query is:-
var resultList = ((JsonArray)searchResults["SearchResults"])
.OfType<JsonObject>()
.Where(o => o.ContainsKey("SEARCHVAL"))
.Select(o => new SearchResult() {
SearchValue = o["SEARCHVALUE"],
Category = o["CATEGORY"].
X = o["X"],
Y = o["Y"]
}).ToList();
The resultList is List<SearchResult> which you can now bind into some Xaml for display.

Resources