option compare binary vb.net
In this article, we will meet how to work with standard value types, custom value types, compress structures to types, and transform from the raw JSON data construction to class structures that back up the needs of our applications.
- Download source code (v1.3) - 1.3 MB
- Download source code (v1.two) - 917.6 KB
- Download source code (v1) - 869.vii KB
Introduction
Whilst JSON is a compact and easy to read cross-language storage and information commutation format, the flexibility that it offers sometimes requires some custom handling to parse the data.
If y'all are not familiar with JSON, then here is a definition from the official http://www.json.org:
Quote:
JSON (JavaScript Object Notation) is a lightweight data-interchange format. Information technology is like shooting fish in a barrel for humans to read and write. Information technology is easy for machines to parse and generate. It is based on a subset of the JavaScript Programming Linguistic communication, Standard ECMA-262 3rd Edition - December 1999.
Contents
- Background
- Tools & Libraries
- Viewers & Validators
- Code Generators
- Serialization Libraries
- Data Conversion
- Standard Data Types
- Elementary Object Types
- Simple Collection Types
- Non-Standard Types and Information Structure Types
- UNIX Epoch Timestamps
- Data Structure Types
- Flattening Collection Types
- Multi-Value Type Collections
- Recursive Deserialization
- Information Transformation
- Summary
- Sample Applications
- History
Background
Why another commodity on JSON? This article was inspired past many questions asked in the Lawmaking Project Quick Questions & Answers section of this website. We will use a number of bones to advanced real-life examples, from Etsy, Flickr, MovieDB, Google Drive, & Twitter, and solutions covering simple object serialization to custom converters and data transformations.
Tools & Libraries
Similar anything, you need the right tools for the job. Here are some of the tools available including those used in this article.
Viewers & Validators
Sometimes, JSON data is packed and not very readable or nosotros need to validate the raw data:
- freeformatter.com - exhaustive support for multiple formats
- codebeautify.org - exhaustive support for multiple formats
- jsonformatter.org - beautify, validate, convert JSON & XML
- jsonformatter.curiousconcept.com - format & validate JSON confronting standards RFC 4627, RFC 7159, ECMA-404
- jsonlint.com - validate JSON
- Visual Studio (VS) Addin: JSON Viewer - format, print, compare, & validate JSON
- Fiddler - web debugging proxy for peeking at HTTP data traffic; run into what is really being sent by the data provider
Lawmaking Generators
Nosotros need to create a class construction to convert the raw JSON data to. You could manually create classes from the JSON file which is a very slow and fourth dimension-consuming task. There are far quicker means to get this done. Here are a couple:
- JSON Utils - supports both VB & C# with lots of options
- Visual Studio Addin: Json2Csharp - Converts JSON information on your clipboard to C# classes
- quicktype.io - supports C#, TypeScript, Go Java, Elm, Swift, Simple Types, and Schemas
Serialization Libraries
Lastly, yous demand to map the raw JSON data to the course structure. Once again, in that location are a few libraries out there:
- Microsoft DataContractJsonSerializer
- Mehdi Gholam's fastJSON
- Newtonsoft's Json.NET
- Yoshifumi Kawai's (a.k.a. neuecc) Utf8Json
For the simple projects, all three libraries cover 99 ~ 100% of the requirements. For more intermediate and avant-garde piece of work like custom data converters and transformations, we need Newtonsoft'southward Json.NET library. This will become more credible later in this commodity.
Information Conversion
One time you have the raw JSON data and created the classes to map the data to, the adjacent pace will be to deserialize to classes & serialize from classes. This article will focus on deserialization. The following helper course simplifies this task.
using Newtonsoft.Json; using System.Collections.Generic; namespace Support.CSharp { public static form JsonHelper { public static string FromClass<T>(T data, bool isEmptyToNull = false, JsonSerializerSettings jsonSettings = zero) { string response = string.Empty; if (!EqualityComparer<T>.Default.Equals(data, default(T))) response = JsonConvert.SerializeObject(data, jsonSettings); render isEmptyToNull ? (response == " {}" ? " cipher" : response) : response; } public static T ToClass<T>(cord information, JsonSerializerSettings jsonSettings = zero) { var response = default(T); if (!string.IsNullOrEmpty(data)) response = jsonSettings == null ? JsonConvert.DeserializeObject<T>(data) : JsonConvert.DeserializeObject<T>(information, jsonSettings); return response; } } }
Imports Newtonsoft.Json Public Module JsonHelper Public Role FromClass(Of T)(data As T, Optional isEmptyToNull Every bit Boolean = Imitation, Optional jsonSettings Equally JsonSerializerSettings = Nothing) _ As String Dim response Equally String = String.Empty If Not EqualityComparer(Of T).Default.Equals(information, Null) And so response = JsonConvert.SerializeObject(data, jsonSettings) End If Render If(isEmptyToNull, (If(response = " {}", " zip", response)), response) Finish Function Public Role ToClass(Of T)(data As String, Optional jsonSettings As JsonSerializerSettings = Null) _ As T Dim response = Nothing If Not String.IsNullOrEmpty(data) Then response = If(jsonSettings Is Nix, JsonConvert.DeserializeObject(Of T)(data), JsonConvert.DeserializeObject(Of T)(information, jsonSettings)) End If Render response End Part End Module
We won't exist using the JsonSerializerSettings. You can read more well-nigh what these are in the Newtonsoft Json.NET documentation.
Standard Information Types
Let us start with something simple. The following ii examples work with the .Net primitive data and collection types.
Unproblematic Object Types
Hither is a Category object from the Etsy API. All JSON fields map to .Net primitive information types.
{ " category_id": 68890752, " name": " gloves", " meta_title": " Handmade Gloves on Etsy - Gloves, mittens, arm warmers", " meta_keywords": " handmade gloves, gloves, handmade arm warmers, handmade fingerless gloves, handmade mittens, hand knit mittens, hand knit gloves, handmade accessories", " meta_description": " Shop for unique, handmade gloves on Etsy, a global handmade marketplace. Scan gloves, arm warmers, fingerless gloves & more from independent artisans.", " page_description": " Shop for unique, handmade gloves from our artisan community", " page_title": " Handmade gloves", " category_name": " accessories\/gloves", " short_name": " Gloves", " long_name": " Accessories > Gloves", " num_children": 3 } We demand to generate class[es] to map the JSON data to. To exercise this, we will use JSON Utils:
Here we have selected Pascal Case naming convention. The JSON fields are all in lower case. Using the Json.Cyberspace JsonProperty attribute, mapping JSON fields to .NET class properties are quite unproblematic. Hither is the course generated:
using Newtonsoft.Json; namespace WinFormSimpleObject.Models { public grade Category { [JsonProperty(" category_id")] public int CategoryId { get; set; } [JsonProperty(" name")] public cord Name { become; prepare; } [JsonProperty(" meta_title")] public string MetaTitle { get; set; } [JsonProperty(" meta_keywords")] public string MetaKeywords { get; set; } [JsonProperty(" meta_description")] public string MetaDescription { get; set up; } [JsonProperty(" page_description")] public string PageDescription { get; set; } [JsonProperty(" page_title")] public string PageTitle { get; set; } [JsonProperty(" category_name")] public string CategoryName { get; set up; } [JsonProperty(" short_name")] public string ShortName { get; set; } [JsonProperty(" long_name")] public string LongName { get; set; } [JsonProperty(" num_children")] public int NumChildren { become; set; } } }
Imports Newtonsoft.Json Namespace Models Public Class Category <JsonProperty(" category_id")> Public Property CategoryId As Integer <JsonProperty(" proper noun")> Public Holding Name As Cord <JsonProperty(" meta_title")> Public Property MetaTitle As Cord <JsonProperty(" meta_keywords")> Public Holding MetaKeywords As String <JsonProperty(" meta_description")> Public Property MetaDescription As String <JsonProperty(" page_description")> Public Property PageDescription As String <JsonProperty(" page_title")> Public Property PageTitle As String <JsonProperty(" category_name")> Public Belongings CategoryName As Cord <JsonProperty(" short_name")> Public Property ShortName Equally String <JsonProperty(" long_name")> Public Property LongName As String <JsonProperty(" num_children")> Public Belongings NumChildren As Integer Cease Class End Namespace
Now we can deserialize the JSON data into .Internet class[es]:
public Category Result { get; set; } private const string fileName = " Etsy_Category.Json"; private readonly cord filePath = Environment.CurrentDirectory; private void GetData() { var rawJson = File.ReadAllText(Path.Combine(filePath, fileName)); Effect = JsonHelper.ToClass<Category>(rawJson); }
Public Property Outcome() Equally Category Private Const fileName As String = " Etsy_Category.Json" Individual ReadOnly filePath As String = Environment.CurrentDirectory Private Sub GetData() Dim rawJson = File.ReadAllText(Path.Combine(filePath, fileName)) Result = JsonHelper.ToClass(Of Category)(rawJson) End Sub
And at present can work with the data. Hither is a screenshot of the attached sample app:
Simple Drove Types
The Etsy API, like many other APIs, work with not only unmarried objects but besides collections of objects wrapped in a JSON response.
{ " count": 27, " results": [{ " category_id": 68890752, " proper noun": " gloves", " meta_title": " Handmade Gloves on Etsy - Gloves, mittens, arm warmers", " meta_keywords": " handmade gloves, gloves, handmade arm warmers, handmade fingerless gloves, handmade mittens, hand knit mittens, mitt knit gloves, handmade accessories", " meta_description": " Shop for unique, handmade gloves on Etsy, a global handmade marketplace. Scan gloves, arm warmers, fingerless gloves & more than from independent artisans.", " page_description": " Shop for unique, handmade gloves from our artisan community", " page_title": " Handmade gloves", " category_name": " accessories\/gloves", " short_name": " Gloves", " long_name": " Accessories > Gloves", " num_children": 3 }, { " category_id": 68890784, " name": " mittens", " meta_title": " Handmade Mittens on Etsy - Mittens, gloves, arm warmers", " meta_keywords": " handmade mittens, handcrafted mittens, mittens, accessories, gloves, arm warmers, fingerless gloves, mittens, etsy, purchase handmade, shopping", " meta_description": " Shop for unique, handmade mittens on Etsy, a global handmade market. Browse mittens, arm warmers, fingerless gloves & more from contained artisans.", " page_description": " Store for unique, handmade mittens from our artisan community", " page_title": " Handmade mittens", " category_name": " accessories\/mittens", " short_name": " Mittens", " long_name": " Accessories > Mittens", " num_children": four }], " params": { " tag": " accessories" }, " type": " Category", " pagination": { } } Hither is our response wrapper:
public class Pagination { [JsonProperty(" effective_limit")] public int? EffectiveLimit { get; fix; } [JsonProperty(" effective_offset")] public int? EffectiveOffset { get; gear up; } [JsonProperty(" effective_page")] public int? EffectivePage { go; set; } [JsonProperty(" next_offset")] public int? NextOffset { become; fix; } [JsonProperty(" next_page")] public int? NextPage { get; set; } } public grade Params { [JsonProperty(" tag")] public string Tag { get; set; } } public form Response<TModel> where TModel : course { [JsonProperty(" count")] public int Count { get; set; } [JsonProperty(" results")] public IList<TModel> Results { get; ready; } [JsonProperty(" params")] public Params Params { become; set; } [JsonProperty(" type")] public string Type { get; set; } [JsonProperty(" pagination")] public Pagination Pagination { get; prepare; } }
Public Class Pagination <JsonProperty(" effective_limit")> Public Property EffectiveLimit() Equally Integer? <JsonProperty(" effective_offset")> Public Property EffectiveOffset() Equally Integer? <JsonProperty(" effective_page")> Public Property EffectivePage() Equally Integer? <JsonProperty(" next_offset")> Public Belongings NextOffset() As Integer? <JsonProperty(" next_page")> Public Belongings NextPage() As Integer? End Class Public Form Params <JsonProperty(" tag")> Public Holding Tag As String Terminate Class Public Class Response(Of TModel As Grade) <JsonProperty(" count")> Public Property Count As Integer <JsonProperty(" results")> Public Holding Results As IList(Of TModel) <JsonProperty(" params")> Public Property Params Every bit Params <JsonProperty(" type")> Public Property Type Equally Cord <JsonProperty(" pagination")> Public Belongings Pagination As Pagination Stop Class
Now we can deserialize the JSON data into .Net class[es]:
public BindingList<Category> Categories { get; ready; } individual void GetData() { var rawJson = File.ReadAllText(Path.Combine(filePath, fileName)); var response = JsonHelper.ToClass<Response<Category>>(rawJson); if (response != null && response.Results != cypher && response.Results.Count > 0) { var information = response.Results; Categories.Clear(); for (int i = 0; i < data.Count; i++) { Categories.Add together(data[i]); } } }
Public Holding Categories() As BindingList(Of Category) Individual Sub GetData() Dim rawJson = File.ReadAllText(Path.Combine(filePath, fileName)) Dim response = JsonHelper.ToClass(Of Response(Of Category))(rawJson) If response IsNot Goose egg _ AndAlso response.Results IsNot Nothing _ AndAlso response.Results.Count > 0 So Dim information = response.Results Categories.Clear() For i Equally Integer = 0 To data.Count - one Categories.Add together(information(i)) Next Terminate If End Sub
Now we can work with the data. Here is a screenshot of the fastened sample app:
Not-Standard Types and Information Structure Types
Not all languages beyond all platforms have compatible information types. Also, providers that support multiple information formats don't ever have clean translations across data formats. The next department will embrace these issues and address them with simple solutions.
UNIX Epoch Timestamps
What is a UNIX epoch timestamp? According to Wikipedia.org:
Quote:
A system for describing instants in fourth dimension, defined as the number of seconds that accept elapsed since 00:00:00 Coordinated Universal Time (UTC), Thursday, 1 January 1970,[1][notation i] minus the number of leap seconds that have taken place since then.
Hither is an case from Twitter:
" reset": 1502612374
And here is an example from Flickr:
" lastupdate": " 1502528455"
Nosotros could have an integer property field and convert the integer epoch timestamp into a DateTime type post deserialization. The alternative and a ameliorate solution is to use a custom JsonConverter attribute:
internal static grade Unix { internal static readonly DateTime Epoch = new DateTime (year: 1970, calendar month: 1, day: 1, hour: 0, minute: 0, 2nd: 0, millisecond: 0, kind: DateTimeKind.Utc); } public static class DoubleExtensions { public static DateTime FromUnixDate(this double? unixDate) { return Unix.Epoch.AddSeconds(unixDate ?? 0.0); } public static DateTime FromUnixDate(this double unixDate) { return Unix.Epoch.AddSeconds(unixDate); } } public sealed course JsonUnixDateConverter : JsonConverter { public override bool CanConvert(Blazon objectType) { render objectType == typeof(DateTime) || objectType == typeof(DateTime?); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { double value = 0; if (double.TryParse(Convert.ToString(reader.Value), out value)) return value.FromUnixDate(); if (objectType == typeof(DateTime)) return default(DateTime); return nix; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } }
Friend Module Unix Friend ReadOnly Epoch As New DateTime(year:=1970, month:=1, day:=1, hour:=0, minute:=0, second:=0, millisecond:=0, kind:=DateTimeKind.Utc) Finish Module Public Module DoubleExtensions <Extension> Public Function FromUnixDate(unixDate As Double?) Equally DateTime Render Epoch.AddSeconds(If(unixDate, 0.0)) Stop Function <Extension> Public Part FromUnixDate(unixDate As Double) Every bit DateTime Render Epoch.AddSeconds(unixDate) End Role End Module Public NotInheritable Course JsonUnixDateConverter : Inherits JsonConverter Public Overrides Role CanConvert(objectType As Blazon) As Boolean Render objectType Is GetType(DateTime) OrElse objectType Is GetType(Date?) Stop Function Public Overrides Function ReadJson(reader Every bit JsonReader, objectType Equally Blazon, existingValue Every bit Object, serializer As JsonSerializer) Every bit Object Dim value As Double = 0 If Double.TryParse(Catechumen.ToString(reader.Value), value) And then Return value.FromUnixDate() End If If objectType Is GetType(DateTime) So Return Nix Terminate If Return Naught Terminate Function Public Overrides Sub WriteJson(author As JsonWriter, value Every bit Object, serializer As JsonSerializer) Throw New NotImplementedException() End Sub Terminate Class
How Information technology Works
The JsonUnixDateConverter.CanConvert checks if it is the correct data blazon(due south). If a match, the JsonUnixDateConverter.ReadJson executes, parses the value, converts from UNIX epoch to .Cyberspace Date type, and returns the value to exist assigned to the class property.
How to Utilize
Merely apply the JsonUnixDateConverter to the property:
[ JsonProperty(" lastupdate"), JsonConverter(typeof(JsonUnixDateConverter))] public DateTime? LastUpdate { go; set; }
<JsonProperty(" lastupdate"), JsonConverter(GetType(JsonUnixDateConverter))> Public Property LastUpdate() As Appointment?
Information Construction Types
Some data providers support multiple data formats: XML, JSON, etc... and differences in the format can create some interesting data structure types. Information structure types are where a single variable type is described as an object rather than a unproblematic value.
Flickr has many examples of this where XML does not directly interpret - XML has both attributes and elements describing data where JSON only has fields. An example of this is the Photo object and the annotate count field:
{ " photo": { " comments": { " _content": " 483" } } } If we do a one-to-one translation, the classes required would be:
public class Comments { [JsonProperty(" _content")] public int Count { get; set up; } } public class Photo { [JsonProperty(" comments")] public Comments Comments { get; fix; } }
public class Comments { [JsonProperty(" _content")] public cord Content { get; set; } } public class Photo { [JsonProperty(" comments")] public Comments Comments { get; set; } }
Then to use the to a higher place course structure:
int GetCommentCount(Photo photograph) { return photograph.Comments.Count; }
Private Function GetCommentCount(photo Equally Photo) As Integer Return photograph.Comments.Count End Function
Information technology would be much ameliorate if we could simplify the Annotate count into a single integer rather than a course object:
int GetCommentCount(Photo photo) { return photograph.CommentCount; }
Private Function GetCommentCount(photo Every bit Photo) As Integer Return photo.CommentCount End Office
Flickr has a number of other value information types that work the same. For example, the photo title field:
" title": { " _content": " North korean regular army Pyongyang North Korea \ubd81\ud55c" }
The solution is a generic JsonConverter:
public sealed class JsonFlickrContentConverter<TModel> : JsonConverter { public override bool CanConvert(Blazon objectType) { return objectType == typeof(TModel); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var result = default(TModel); switch (reader.TokenType) { example JsonToken.Integer: instance JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Date: effect = (TModel)Convert.ChangeType(reader.Value, GetUnderlyingType()); break; case JsonToken.StartObject: GetObject(reader, out result); break; } return result; } private void GetObject(JsonReader reader, out TModel result) { var tags = JObject.Load(reader).FindTokens(" _content"); outcome = (tags != zilch && tags.Count > 0) ? (TModel)Convert.ChangeType((string)tags[0], GetUnderlyingType()) : result = default(TModel); } private Blazon GetUnderlyingType() { var type = typeof(TModel); render Nullable.GetUnderlyingType(blazon) ?? type; } public override void WriteJson(JsonWriter author, object value, JsonSerializer serializer) { throw new NotImplementedException(); } }
Public NotInheritable Form JsonFlickrContentConverter(Of TModel) : Inherits JsonConverter Public Overrides Role CanConvert(objectType Equally Type) As Boolean Return objectType = GetType(TModel) Terminate Function Public Overrides Office ReadJson(reader As JsonReader, _ objectType Every bit Type, existingValue As Object, serializer Equally JsonSerializer) As Object Dim result = Nothing Select Case reader.TokenType Case JsonToken.[Integer], JsonToken.Bladder, JsonToken.[String], JsonToken.[Boolean], JsonToken.[Date] result = DirectCast(Catechumen.ChangeType_ (reader.Value, GetUnderlyingType()), TModel) Exit Select Case JsonToken.StartObject GetObject(reader, consequence) Exit Select Cease Select Return effect End Function Private Sub GetObject(reader As JsonReader, ByRef issue Every bit TModel) Dim tags = JObject.Load(reader).FindTokens(" _content") event = If((tags IsNot Goose egg AndAlso tags.Count > 0), DirectCast(Convert.ChangeType(CType(tags(0), String), _ GetUnderlyingType()), TModel), Aught) Cease Sub Private Function GetUnderlyingType() As Type Dim type = GetType(TModel) Return If(Nullable.GetUnderlyingType(type), type) Terminate Function Public Overrides Sub WriteJson(author As JsonWriter, _ value Equally Object, serializer Every bit JsonSerializer) Throw New NotImplementedException() Terminate Sub End Class
And to employ:
public class Photo { [JsonProperty(" comments"), JsonConverter(typeof(JsonFlickrContentConverter<int?>))] public int? Comments { go; fix; } }
Public Class Photo <JsonProperty(" comments"), JsonConverter(GetType(JsonFlickrContentConverter(Of Integer?)))> Public Property Comments() As Integer? Stop Class
Flattening Collection Types
Like data structure types, a drove of objects besides sometimes exercise not translate well from XML to JSON. Flickr has many examples of this. The Photo.Notes collection is a typical example:
" notes": { " notation": [{ " id": " 72157613689748940", " author": " 22994517@N02", " authorname": " morningbroken", " authorrealname": " ", " authorispro": 0, " x": " 227", " y": " 172", " w": " 66", " h": " 31", " _content": " Peradventure ~ I recollect ...She is very happy ." }, { " id": " 72157622673125344", " writer": " 40684115@N06", " authorname": " Suvcon", " authorrealname": " ", " authorispro": 0, " x": " 303", " y": " 114", " w": " 75", " h": " 60", " _content": " this guy is different." }] },
Grade construction would be:
public form Photo { [JsonProperty(" notes")] public Notes Notes { go; set; } } public class Notes { [JsonProperty(" annotation")] public IList<Notation> Note { become; set; } }
Public Grade Photo <JsonProperty(" notes")> Public Property Notes Equally Notes End Class Public Class Notes <JsonProperty(" annotation")> Public Holding Note As IList(Of Notation) Stop Class
As you tin run into, we end upwardly with an actress unwanted Notes form to hold the list of Note.
The following generic JsonConverter will shrink this to return return a List<TModel> for the Photo class:
public sealed form JsonFlickrCollectionConverter<TModel> : JsonConverter where TModel : grade { public override bool CanConvert(Blazon objectType) { return objectType == typeof(TModel); } public override object ReadJson(JsonReader reader, _ Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.StartObject) { var jObj = JObject.Load(reader); if (jObj.HasValues) { var items = new List<TModel>(); foreach (var value in jObj.Values()) { endeavour { items.AddRange(JsonHelper.ToClass<IList<TModel>>(value.ToString())); } catch (Exception) { return null; } } render items; } } return naught; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } }
Public NotInheritable Class JsonFlickrCollectionConverter(Of TModel As Class) : _ Inherits JsonConverter Public Overrides Office CanConvert(objectType Equally Type) As Boolean Return objectType = GetType(TModel) End Function Public Overrides Office ReadJson(reader Every bit JsonReader, _ objectType As Type, existingValue As Object, serializer As JsonSerializer) Equally Object If reader.TokenType = JsonToken.StartObject Then Dim jObj = JObject.Load(reader) If jObj.HasValues Then Dim items = New List(Of TModel) For Each value In jObj.Values() Attempt items.AddRange(JsonHelper.ToClass_ (Of IList(Of TModel))(value.ToString())) Catch generatedExceptionName As Exception Return Nix End Try Adjacent Return items Cease If End If Return Nothing Cease Role Public Overrides Sub WriteJson(writer As JsonWriter, _ value Every bit Object, serializer As JsonSerializer) Throw New NotImplementedException() Cease Sub Stop Class
And to utilize:
[ JsonProperty(" notes"), JsonConverter(typeof(JsonFlickrCollectionConverter<Note>))] public IList<Notation> Notes { get; set; }
<JsonProperty(" notes"), JsonConverter(GetType(JsonFlickrCollectionConverter(Of Notation)))> Public Property Notes() As IList(Of Note)
Multi-Value Type Collections
This is where a drove of objects returned are of similar or dissimilar complex object types. themoviedb.org Multi search returns Boob tube, Move, and Person types in the same collection. Google Bulldoze is another example that returns a collection with File and Folder complex object types.
MovieDB.Org
Here is a screenshot of the included MovieDB demo app that shows an example of this:
The JSON data for the higher up screenshot looks similar this:
{ " folio": 1, " total_results": 3433, " total_pages": 172, " results": [ { " original_name": " Captain N and the New Super Mario World", " id": 26732, " media_type": " telly", " proper noun": " Helm N and the New Super Mario World", " vote_count": 2, " vote_average": iii.5, " poster_path": " /i4Q8a0Ax5I0h6b1rHOcQEZNvJzG.jpg", " first_air_date": " 1991-09-14", " popularity": 1.479857, " genre_ids": [ 16, 35 ], " original_language": " en", " backdrop_path": " /iYT5w3Osv3Bg1NUZdN9UYmVatPs.jpg", " overview": " Super Mario World is an American animated television series loosely based on the Super NES video game of the same name. It is the tertiary and last Sabbatum morning drawing based on the Super Mario Bros. NES and Super NES series of video games. The show only aired xiii episodes due to Captain North: The Game Master's cancellation on NBC. Just like The Adventures of Super Mario Bros. 3, the series is produced past DIC Amusement and Reteitalia Southward.P.A in association with Nintendo, who provided the characters and power-ups from the game.", " origin_country": [ " U.s.a." ] }, { " popularity": 1.52, " media_type": " person", " id": 1435599, " profile_path": zilch, " name": " Small World", " known_for": [ { " vote_average": 8, " vote_count": 1, " id": 329083, " video": false, " media_type": " film", " championship": " One For The Route: Ronnie Lane Memorial Concert", " popularity": 1.062345, " poster_path": " /i8Ystwg81C3g9a5z3ppt3yO1vkS.jpg", " original_language": " en", " original_title": " One For The Road: Ronnie Lane Memorial Concert", " genre_ids": [ 10402 ], " backdrop_path": " /oG9uoxtSuokJBgGO4XdC5m4uRGU.jpg", " developed": false, " overview": " At The Royal Albert Hall, London on 8th April 2004 after some 15 months of planning with Paul Weller, Ronnie Forest, Pete Townshend, Steve Ellis, Midge Ure, Bounding main Colour Scene amongst them artists assembled to perform to a sell-out venue and to pay tribute to a man who co-wrote many Modern anthems such as \"\"Itchycoo Park, All Or Zippo, Here Comes The Nice, My Mind's Eye\"\" to proper noun only a few. Ronnie Lane was the creative heart of two of Rock n Rolls quintessentially English groups, firstly during the 60's with The Minor Faces then during the 70;s with The Faces. After the split of the Faces he then formed Slim Take a chance and toured the Britain in a giant circus tent as well as working in the studio with Eric Clapton, Pete Townshend and Ronnie Woods. five,500 fans looked on in awe at The R.A.H as the superb evening's amusement concluded with \"\"All Or Nothing\"\" featuring a surprise advent past Chris Farlowe on pb vocals.", " release_date": " 2004-09-24" } ], " adult": simulated }, { " vote_average": half dozen.8, " vote_count": 4429, " id": 76338, " video": fake, " media_type": " movie", " title": " Thor: The Nighttime World", " popularity": 10.10431, " poster_path": " /bnX5PqAdQZRXSw3aX3DutDcdso5.jpg", " original_language": " en", " original_title": " Thor: The Night World", " genre_ids": [ 28, 12, 14 ], " backdrop_path": " /3FweBee0xZoY77uO1bhUOlQorNH.jpg", " adult": false, " overview": " Thor fights to restore social club beyond the creation… but an ancient race led by the vengeful Malekith returns to plunge the universe dorsum into darkness. Faced with an enemy that even Odin and Asgard cannot withstand, Thor must embark on his well-nigh perilous and personal journey yet, one that will reunite him with Jane Foster and force him to cede everything to save us all.", " release_date": " 2013-10-29" } ] } The primal to identifying the different circuitous data types is with a key field. In the above MovieDB JSON data example, the key field is media_type.
When we define the classes for the three data types TV, Movie, and Person, we will use a simple Interface confronting each class type for the collection:
public interface IDataType { }
Public Interface IDataType End Interface
A custom JsonConverter JsonDataTypeConverter is used on the drove. It identifies the object type and generates the appropriate class and populates the fields:
public sealed grade JsonDataTypeConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(IDataType); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { Listing<IDataType> results = aught; if (reader.TokenType== JsonToken.StartArray) { var jObjs = serializer.Deserialize<IList<JObject>>(reader); if (jObjs != nothing && jObjs.Count > 0) { results = new List<IDataType>(); for (int i = 0; i < jObjs.Count; i++) { var token = jObjs[i].FindTokens(" media_type"); if (token != cypher && token.Count > 0) { switch (token[0].ToString()) { case " tv": results.Add(Convert<Television>(jObjs[i])); interruption; instance " movie": results.Add(Convert<Movie>(jObjs[i])); break; case " person": results.Add together(Convert<Person>(jObjs[i])); break; } } } } } return results; } private TModel Convert<TModel>(JObject jObj) where TModel : IDataType { render JsonHelper.ToClass<TModel>(jObj.ToString()); } public override void WriteJson(JsonWriter author, object value, JsonSerializer serializer) { throw new NotImplementedException(); } }
Public NotInheritable Class JsonDataTypeConverter : Inherits JsonConverter Public Overrides Function CanConvert(objectType Every bit Blazon) As Boolean Return objectType = GetType(IDataType) End Part Public Overrides Part ReadJson(reader As JsonReader, objectType Equally Type, _ existingValue As Object, serializer As JsonSerializer) As Object Dim results As List(Of IDataType) = Nothing If reader.TokenType = JsonToken.StartArray Then Dim jObjs = serializer.Deserialize(Of IList(Of JObject))(reader) If jObjs IsNot Null AndAlso jObjs.Count > 0 And then results = New List(Of IDataType)() For i As Integer = 0 To jObjs.Count - 1 Dim token = jObjs(i).FindTokens(" media_type") If token IsNot Nothing AndAlso token.Count > 0 And so Select Case token(0).ToString() Instance " tv" results.Add(Catechumen(Of Tv)(jObjs(i))) Go out Select Case " moving picture" results.Add(Convert(Of Flick)(jObjs(i))) Go out Select Case " person" results.Add(Convert(Of Person)(jObjs(i))) Exit Select End Select End If Next End If End If Return results End Office Private Function Convert(Of TModel As IDataType)(jObj Every bit JObject) Equally TModel Render JsonHelper.ToClass(Of TModel)(jObj.ToString()) End Office Public Overrides Sub WriteJson(writer As JsonWriter, _ value Every bit Object, serializer As JsonSerializer) Throw New NotImplementedException() Cease Sub End Class
And to use:
public class Response { [JsonProperty(" results"), JsonConverter(typeof(JsonDataTypeConverter))] public IList<IDataType> Results { get; set up; } }
Public Class Response <JsonProperty(" results"), JsonConverter(GetType(JsonDataTypeConverter))> Public Property Results() As IList(Of IDataType) End Grade
Below is a screenshot of the collection when viewing the IntelliSense debug window showing the collection with multiple object types:
Google Bulldoze
Another case of this is Google Drive API. The File blazon, for example, has two identifiers: one to differentiate between Files and Folder, and another for the type of File - Jpg, Png, Text file, Document, MP4, etc. This can be seen in the JSON data.
{ " kind": " drive#fileList", " incompleteSearch": false, " files": [ { " kind": " drive#file", " mimeType": " video/mp4" }, { " kind": " bulldoze#file", " mimeType": " application/vnd.google-apps.folder" }, { " kind": " drive#file", " mimeType": " application/vnd.openxmlformats-officedocument.presentationml.presentation" }, { " kind": " drive#file", " mimeType": " application/vnd.openxmlformats-officedocument.wordprocessingml.certificate" }, { " kind": " bulldoze#file", " mimeType": " text/plain" }, { " kind": " drive#file", " mimeType": " image/png" } ] } The dissimilar File types tin be seen reflected in the following sample awarding screenshot:
The sample app higher up works with a Hierarchical data structure and loads each branch's information on-demand as it is opened.
All the different types of files have the aforementioned data. So nosotros tin can declare a base type and inherit it for all the different types of files.
public form File : IResourceKind { [JsonProperty(" kind")] public cord Kind { go; ready; } [JsonProperty(" mimeType")] public cord MimeType { become; gear up; } } public class Binder : File { } public class TxtDocument : File { } public class WordDocument : File { } public grade PngImage : File { } public class JpgImage : File { } public class Zipped : File { }
Public Class File : Implements IResourceKind <JsonProperty(" kind")> Public Property Kind Equally String <JsonProperty(" mimeType")> Public Property MimeType As String End Class Public Course Folder : Inherits File End Class Public Class TxtDocument : Inherits File End Class Public Class WordDocument : Inherits File End Class Public Class PngImage : Inherits File End Class
Side Note: When when working with Implicit templates in XAML, you tin ascertain a default template, in this example for the base File Type, and if an implicit template is not found for the information blazon (class), the base of operations template is practical for the inherited base grade type.
< DataTemplate DataType =" {x:Type yard:File}" > < /DataTemplate >
As in that location is a common base type for a large number of File types, a compact handler inside a client JsonConverter, JsonDataTypeConverter for Google Bulldoze, can be used. Here we volition have a lookup Dictionary Tabular array for the "mime_type" JSON field and method reference with conversion blazon.
private readonly Lexicon<cord, Func<JObject, File>> mimeTypes = new Dictionary<cord, Func<JObject, File>> { { " application/vnd.google-apps.folder", Convert<Folder>() }, { " paradigm/jpeg", Catechumen<JpgImage>() }, { " paradigm/png", Convert<PngImage>() }, { " awarding/zip", Catechumen<Zipped>() }, { " application/x-zilch-compressed", Convert<Zipped>() }, { " video/mp4", Catechumen<Mp4Video>() }, { " text/plainly", Convert<TxtDocument>() }, { " application/vnd.openxmlformats-officedocument.presentationml.presentation", Convert<PptDocument>() }, { " application/vnd.openxmlformats-officedocument.wordprocessingml.document", Convert<WordDocument>() } }; individual void ProcessFileType(List<File> results, IList<JObject> jObjs, int i) { var fileToken = jObjs[i].FindTokens(" mimeType"); if (fileToken != naught && fileToken.Count > 0) { var key = mimeTypes.Keys.FirstOrDefault(ten => x.Equals(fileToken[0].ToString())); if (key != cipher) { results.Add(mimeTypes[cardinal](jObjs[i])); } } } private static Func<JObject, File> Convert<TModel>() where TModel : File { return (jObj) => JsonHelper.ToClass<TModel>(jObj.ToString()); }
Individual ReadOnly mimeTypes As New Dictionary(Of String, Func(Of JObject, File))() From { {" application/vnd.google-apps.binder", Convert(Of Binder)()}, {" epitome/jpeg", Convert(Of JpgImage)()}, {" epitome/png", Catechumen(Of PngImage)()}, {" application/naught", Catechumen(Of Zipped)()}, {" awarding/ten-zip-compressed", Convert(Of Zipped)()}, {" video/mp4", Convert(Of Mp4Video)()}, {" text/obviously", Catechumen(Of TxtDocument)()}, {" application/vnd.openxmlformats-officedocument.presentationml.presentation", Convert(Of PptDocument)()}, {" application/vnd.openxmlformats-officedocument.wordprocessingml.certificate", Convert(Of WordDocument)()} } Private Sub ProcessFileType(results As List(Of File), jObjs Equally IList(Of JObject), i As Integer) Dim fileToken = jObjs(i).FindTokens(" mimeType") If fileToken IsNot Nothing AndAlso fileToken.Count > 0 Then Dim primal = mimeTypes.Keys.FirstOrDefault(Function(x) x.Equals(fileToken(0).ToString())) If fundamental IsNot Cypher And then results.Add(mimeTypes(central)(jObjs(i))) Cease If Stop If Cease Sub Private Shared Part Convert(Of TModel Equally File)() Equally Func(Of JObject, File) Return Function(jObj) JsonHelper.ToClass(Of TModel)(jObj.ToString()) Stop Function
The IntelliSense debug window for the File collection property correctly reflects the recursive deserialization of the different File types:
Recursive Deserialization
JSON object structures tin be many node levels deep. Each node could have properties with their own custom JsonConverters. An example of this is the MovieDB in a higher place in the previous section Multi-Value Blazon Collections. Hither is an extract for the Person JSON node construction with the node collection known_for :
{ " folio": ane, " total_results": 3433, " total_pages": 172, " results": [ { " media_type": " television set", }, { " media_type": " person", " known_for": [ { " media_type": " movie", } ] }, { " media_type": " motion-picture show", } ] } The JsonDataTypeConverter form above already supports recursive deserialization. Once the node object blazon is identified, we re-call the JsonHelper.ToClass<...>(...) method:
private TModel Convert<TModel>(JObject jObj) where TModel : IDataType { return JsonHelper.ToClass<TModel>(jObj.ToString()); }
Private Part Convert(Of TModel As IDataType)(jObj As JObject) As TModel Render JsonHelper.ToClass(Of TModel)(jObj.ToString()) Stop Function
And in the Person form, we apply the JsonConverter aspect JsonDataTypeConverter:
public form Person : RecordBase { [JsonProperty(" known_for"), JsonConverter(typeof(JsonDataTypeConverter))] public IList<IDataType> KnownFor { get; set; } }
Public Grade Person : Inherits RecordBase <JsonProperty(" known_for"), JsonConverter(GetType(JsonDataTypeConverter))> Public Property KnownFor As IList(Of IDataType) End Class
Hither, we can see from the IntelliSense debug window for the Person. KnownFor drove property and correctly reflects the recursive deserialization of the Movie class type:
Data Transformation
Normally, to transform data, it is a 2-footstep procedure. Offset, we catechumen the JSON information to .Cyberspace classes (34 classes in total in this example), then transform the data.
The terminal example that I have demonstrated how to transform the JSON data to a custom course collection in a unmarried step. By doing this, we have reduced the number of classes required, in this case, from 34 to 4!
Hither is what the end event will look like:
As there are likewise many information classes to mail service here, I will but discuss the JsonConverter used. You can view and run the sample project,WpfApplicationRateLimitStatus which is included in the download. I accept included both the standard and custom mapping classes.
The JsonApiRateLimitsConverter compresses the multiple classes into a simpler collection of data that is compatible with the application'southward requirements.
public sealed class JsonApiRateLimitsConverter : JsonConverter { public override bool CanConvert(Blazon objectType) { render objectType == typeof(RateCategoryModel); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { ObservableCollection<RateCategoryModel> result = null; if (reader.TokenType == JsonToken.StartObject) { var jObj = JObject.Load(reader); if (jObj.HasValues) { issue = new ObservableCollection<RateCategoryModel>(); foreach (var child in jObj.Children()) { var rate = ProcessChild(kid, serializer); if (rate != zip) result.Add together(charge per unit); } } } return outcome; } individual static RateCategoryModel ProcessChild(JToken child, JsonSerializer serializer) { RateCategoryModel charge per unit = null; var node = serializer.Deserialize<JProperty>(child.CreateReader()); if (node.HasValues) { charge per unit = new RateCategoryModel { Proper name = node.Proper noun }; foreach (var item in node.Values()) { var limit = serializer.Deserialize<JProperty>(item.CreateReader()); rate.Limits.Add together(new RateLimitModel { Name = GetPropertyName(limit), Limit = GetRateLimit(limit) }); } } return rate; } individual static string GetPropertyName(JProperty prop) { string proper name = string.Empty; if (!string.IsNullOrEmpty(prop.Name)) { var parts = prop.Name.Split(new[] { ' /' }, StringSplitOptions.RemoveEmptyEntries); name = string.Join(" _", parts.Skip(ane)).Supervene upon(" :", " "); if (string.IsNullOrEmpty(name)) proper noun = prop.Name.Supplant(" /", " "); } else { name = " __noname__"; } return name; } private static ApiRateLimitModel GetRateLimit(JProperty limit) { ApiRateLimitModel model = aught; if (!cord.IsNullOrEmpty(limit.First.ToString())) { var rawJson = limit.Offset.ToString(); model = JsonHelper.ToClass<ApiRateLimitModel>(rawJson); } render model; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } }
Public NotInheritable Class JsonApiRateLimitsConverter : Inherits JsonConverter Public Overrides Role CanConvert(objectType As Type) As Boolean Return objectType = GetType(RateCategoryModel) Terminate Function Public Overrides Office ReadJson(reader As JsonReader, _ objectType Equally Type, existingValue As Object, serializer As JsonSerializer) Every bit Object Dim result As ObservableCollection(Of RateCategoryModel) = Nada If reader.TokenType = JsonToken.StartObject Then Dim jObj = JObject.Load(reader) If jObj.HasValues Then result = New ObservableCollection(Of RateCategoryModel)() For Each kid In jObj.Children() Dim rate = ProcessChild(child, serializer) If rate IsNot Goose egg So result.Add(rate) Finish If Next End If Cease If Return result Terminate Function Private Shared Part ProcessChild(child As JToken, _ serializer As JsonSerializer) As RateCategoryModel Dim rate As RateCategoryModel = Nothing Dim node = serializer.Deserialize(Of JProperty)(child.CreateReader()) If node.HasValues So charge per unit = New RateCategoryModel() With {.Name = node.Proper name} For Each detail In node.Values() Dim limit = serializer.Deserialize(Of JProperty)(particular.CreateReader()) rate.Limits.Add(New RateLimitModel() With { .Proper name = GetPropertyName(limit), .Limit = GetRateLimit(limit) }) Adjacent Finish If Return charge per unit End Function Private Shared Function GetPropertyName(prop Equally JProperty) Equally Cord Dim name As String = Cord.Empty If Not String.IsNullOrEmpty(prop.Name) And so Dim parts = prop.Name.Split(New Char() _ {" /"c}, StringSplitOptions.RemoveEmptyEntries) name = String.Join(" _", parts.Skip(ane)).Replace(" :", " ") If Cord.IsNullOrEmpty(name) Then name = prop.Name.Supersede(" /", " ") Finish If Else name = " __noname__" End If Render name Terminate Office Individual Shared Role GetRateLimit(limit Every bit JProperty) Every bit ApiRateLimitModel Dim model As ApiRateLimitModel = Nix If Not String.IsNullOrEmpty(limit.First.ToString()) And so Dim rawJson = limit.Starting time.ToString() model = JsonHelper.ToClass(Of ApiRateLimitModel)(rawJson) Stop If Return model Finish Role Public Overrides Sub WriteJson(author Every bit JsonWriter, _ value As Object, serializer As JsonSerializer) Throw New NotImplementedException() End Sub
And to use:
public class APIRateStatusModel { [JsonProperty(" resource"), JsonConverter(typeof(JsonApiRateLimitsConverter))] public ObservableCollection<RateCategoryModel> Resources { go; set; } }
Public Class APIRateStatusModel <JsonProperty(" resources"), JsonConverter(GetType(JsonApiRateLimitsConverter))> Public Property Resources() As ObservableCollection(Of RateCategoryModel) End Class
private void GetData() { var rawJson = File.ReadAllText(Path.Combine(filePath, fileName)); Upshot = JsonHelper.ToClass<APIRateStatusModel>(rawJson); }
Individual Sub GetData() Dim rawJson = File.ReadAllText(Path.Combine(filePath, fileName)) Result = JsonHelper.ToClass(Of APIRateStatusModel)(rawJson) End Sub
Summary
Nosotros accept covered how to work with standard value types, custom value types, compress structures to types, and transform from the raw JSON data structure to course structures that support the needs of our applications. Newtonsoft's Json.NET, the Helper classes, and the custom JsonConverters makes working with JSON data make clean and very easy.
Sample Applications
There are six (half dozen) sample applications, both in C# and VB, included in the download:
-
WinFormSimpleObject- Etsy Category-
WinForm, lawmaking-backside
-
-
WinFormSimpleCollection- Etsy Categories-
WinForm,Datbinding, MVVM (simple)
-
-
WpfPhoto- Flickr Photo Viewer- WPF, MVVM
-
JsonFlickrCollectionConverter,JsonFlickrContentConverter,JsonFlickrUnixDateContentConverter,JsonFlickrUriContentConverter,StringEnumConverter
-
WpfMultiSearch- MovieDB MultiSearch result- WPF, MVVM, Implicit Templates
-
JsonDataTypeConverter,JsonPartialUrlConverter
-
WpfApplicationRateLimitStatus- Twitter JSON data Transformation- WPF, MVVM,
DataGrid -
JsonUnixDateConverter,JsonApiRateLimitsConverter
- WPF, MVVM,
-
WpfFileExplorer- Google Drive File Explorer- WPF, MVVM,
TreeViewwith load-on-demand & custom template, Implicit Templates, HierarchicalDataBinding -
JsonDataTypeConverter,JsonGoogleUriContentConverter
- WPF, MVVM,
A download link for all the samples is provided above.
History
- v1.0 - August 15, 2017 - Initial release
- v1.1 - August 16, 2017 - Added reference to Fiddler in the Viewers & Validators section
- v1.ii - Baronial 16, 2017 - Added new Recursive Deserialization section (thanks BillWoodruff for the suggestion); new download with pocket-size update to C#/VB WpfMultiSearch sample
- v1.3 - August 19, 2017 - Added new Google Drive File Explorer sample app to demonstrate another version of Multi-Value Type Collections with multiple identifier keys for file type class support broken down in the Multi-Value Type Collections section
- v1.4 - October 26, 2017 - Added table of contents for like shooting fish in a barrel navigation; added lawmaking generator quicktype.io; added serialization library Utf8Json
Source: https://www.codeproject.com/Articles/1201466/Working-with-JSON-in-Csharp-VB
Posted by: mageeshawat47.blogspot.com

0 Response to "option compare binary vb.net"
Post a Comment