Deserialize json that has some property name starting with a number - c#

JSON data looks like this
[
{
"market_id": "21",
"coin": "DarkCoin",
"code": "DRK",
"exchange": "BTC",
"last_price": "0.01777975",
"yesterday_price": "0.01770278",
"change": "+0.43",
"24hhigh": "0.01800280",
"24hlow": "0.01752015",
"24hvol": "404.202",
"top_bid": "0.01777975",
"top_ask": "0.01790000"
}
]
Notice these 3 properties here 24high, 24hhlow, and 24hvol
how do you make a class for that. I need all those properties by the way, not just those 3 properties I mentioned.

You should use JSON.NET or similar library that offers some more advanced options of deserialization. With JSON.NET all you need is adding JsonProperty attribute and specify its custom name that appears in resulting JSON. Here is the example:
public class MyClass
{
[JsonProperty(PropertyName = "24hhigh")]
public string Highest { get; set; }
...
Now to deserialize:
string jsonData = ...
MyClass deserializedMyClass = JsonConvert.DeserializeObject<MyClass>(jsonData);

For .NET Core 3.0 and beyond, you can now use the System.Text.Json namespace. If you are using this:
public class MyClass
{
...
[JsonPropertyName("24hhigh")]
public string twentyFourhhigh { get; set; }
...
}
You can use JsonPropertyName Attribute.

Related

Need help deserializing C# / .NET 6 into seperate objects

I am attempting to use JsonSerializer.Deserialize() from System.Text.JSON in .NET 6.
I have no control over the format of the JSON.
I have used it successfully in the past but now the data I need to consume is more complicated (but not VERY complicated). I am assuming that I am simply describing my data incorrectly.
I have tried several things.... but the description below is the only way so far that I could consume the data at all.
I think my biggest problem is that I am trying to use the wiz-bang "Paste Special -> Paste JSON as Classes" without really understanding how to form my classes for serialization/deserialization.
Here is a simple example of the JSON I am trying to consume:
[
{
"version": "1.0b",
"sub_version": "x.y.barf"
},
{
"somestring": "I am a string",
"isCool": false,
"a_cool_array": [
"bob",
"jill",
"pete"
]
}
]
If I use the whiz-bang "Paste Special" tool, I get the following generated for me.
public class Rootobject
{
public Class1[] Property1 { get; set; }
}
public class Class1
{
public string version { get; set; }//<-- I need these to remain in their own object
public string sub_version { get; set; }//<-- I need these to remain in their own object
public string somestring { get; set; }
public bool isCool { get; set; }
public string[] a_cool_array { get; set; }
}
Here is the problem that I have.
The whiz-bang tool put my first object (with one version strings) and second (more complicated) object into the same object.
If I use a call like this:
var deserializedJSON = JsonSerializer.Deserialize<List<Class1>>(myJSONTextHere);
I end up with two objects in the list.
The first one has the versions filled out, the second one only has the other fields filled out.
This all makes sense to me but I don't know how to get around the problem.
I need these objects to model the JSON and I need them to save back in the same format when I re-serailize the modified classes elsewhere. This isn't my exact problem as I have simplified it for the question.
I have found one way around this problem.
It is ugly but seems to work. I hate that my code has to know about the data it is manipulating.
I used the actual JSON DOM to split the two disparate classes into individual JSON objects, then used the class de-serializer to load the individual objects into their given types.
In the following example, I am not checking anything.. I happen to know the order of the objects. I could check the raw JSON to make sure it was what I was looking for. In this case, I don't need to.
So, instead of taking the class structure as pasted by the super spiffy "Paste Classes from JSON" thingamajigger.. I split the classes myself.
Like this:
public class VersionClass
{
public string version { get; set; }
public string sub_version { get; set; }
}
public class DataClass
{
public string somestring { get; set; }
public bool isCool { get; set; }
public string[] a_cool_array { get; set; }
}
Then, I can load the JSON into the objects I need like this:
using var jsonDoc = JsonDocument.Parse(jsonText);
var versionClass = jsonDoc.RootElement[0].Deserialize<VersionClass>();
var dataClass = jsonDoc.RootElement[1].Deserialize<DataClass>();
I hope this helps someone having the same problem.
Your json needs to look like this:
{
"class1": [
//more json
],
"class2": [
//more json
]
}
Then you will have:
public class RootObject
{
// class1 and 2 in here
}
public class Class1
{
}
public class Class2
{
}

How to mark certain property as required in json content

I am writing an application where I do need to handle some scenarios beforehand in my controller class like certain property must have been provided otherwise status code would be BadRequest. Here is my class lookalike.
public class MyClass
{
[Required]
public IEnumerable<NewObject> NewObjects { get; set; }
}
public class NewObject : INewObject
{
public NewObject(string typeName, IEnumerable<Property> properties)
{
TypeName = typeName;
Properties = properties;
}
[JsonProperty(Required = Required.Always)]
public string TypeName { get; }
public IEnumerable<IProperty> Properties { get; }
}
public interface IProperty
{
string Name { get; }
object Value { get; }
}
Now though I have marked TypeName as required property and if I do not pass that in json content while sending request from swagger, json deserialization doesn't fail. I tried to search but I got an answer that setting Required to Always should work.
Below is the Json Content I am passing through swagger:
{
"NewObjects": [
{
"Properties": [
{
"Name": "string",
"Value": ''
}
]
}
]
}
I wrote below piece of code too by looking at one of the solution:
var config = new HttpConfiguration();
var jsonFormatter = config.Formatters.JsonFormatter;
jsonFormatter.SerializerSettings.MissingMemberHandling = MissingMemberHandling.Error;
config.MapHttpAttributeRoutes();
Still it's not working:
Note: I am using Newtonsoft.Json version 11.0.1
This seems to be swagger issue because when I serialize input C# object and when again deserialize it, I am getting proper error.
For example in my controller class if I say:
var input2 = JsonConvert.DeserializeObject<MyClass>(JsonConvert.SerializeObject(input))
Then input2 throws an exception.
You can take a look at FluentValidation. If I am not mistaken it is designed to validate data in jsons forms specifically.
using FluentValidation;
public CertainActionValidator()
{
RuleFor(x => x.PropertyName).NotEmpty()
}
You can add plenty of additional conditions in there.

Designing c# class from json template

I have to design a class based on a json template that i received. I'm stuck at this part of the json:
events: {
"door": [
5,
{
valueone: 27,
valuetwo: "something"
}
],
"window": [
2,
{
valueone: 13,
valuetwo: "something"
}
]
}
The best i can come up with is this property in the root object:
public Dictionary<string, EventData> Events { get; set; }
Where Events is defined like this:
public class EventData
{
public int valueone { get; set; }
public string valuetwo { get; set; }
}
This gives me for example the following output:
Events: {
door: {
valueone: 27,
valuetwo: "something"
}
}
But i have no idea how to design the class to get the numbers in the json example (5 and 2) in the output. I have tried to google for this for a long time today but i'm not quite sure what to search for.
Below is an outline of the code that would fit:
public class Event
{
public List<Elements> door { get; set; }
public List<Elements> window { get; set; }
}
public sealed class Elements
{
public int Id {get; set;}
public IDictionary<string, string> Values { get; set;}
}
You could build your objects with C# then use JSON.Net to serialise them to there JSON counterpart using:
Newtonsoft.Json.JsonConvert.SerializeObject(YOUR-OBJECT-HERE)
Depending on your needs you don't necessarily have to define types for capturing json like that:
For parsing you can use dynamic to capture the json as parsed by some json libararies.
For serializing json you can define anonymous objects like so
Json.Stringify(new {
events = new {
door = new[] {
5,
new { ... }
}
}
});
If you do need to define explicit types (because you want a model in your c# program) you may want to get more clarity about the domain that you are about to model. You can mirror the same JSON with different C# structures, so what really matters here is what the business/requirements do or will look like.
As #Habib noted in his comment you can use json2csharp.com to give you a hint (I did not know of that service until now - looks interesting!), but json2csharp.com will not be able to answer those questions.
Note: The "json" as it stands in your question is not valid JSON.

Deserializing a JSON with variable name/value pairs into object in C#

I am using C# .NET 4.0 to parse a JSON into a custom object. I am using JavaScriptSerializer.Deserialize to map it to a class that I wrote. Problem is, the JSON's name/value pairs are not static and vary depending on the argument isChain, as seen in this JSON fragment (better link at bottom):
{
"STATE_WALK_LEFT":{
"isChain":"1",
"x":"1"
},
"STATE_WALK_LEFT_0":{
"x":"0"
},
"STATE_WALK_LEFT_1":{
"x":"40"
},
"STATE_WALK_LEFT_2":{
"x":"80"
},
"STATE_WALK_RIGHT":{
"isChain":"0"
},
"STATE_RUN_LEFT":{
"isChain":"0"
}
}
The chains can have anywhere from _STATE_0 to _STATE_25 entries in the chains. Is there some way to store this data so I don't have to write 12*26 empty classes like so:
public StateWalkLeft0 STATE_WALK_LEFT { get; set; }
public StateWalkLeft0 STATE_WALK_LEFT_0 { get; set; }
public StateWalkLeft1 STATE_WALK_LEFT_1 { get; set; }
public StateWalkLeft2 STATE_WALK_LEFT_2 { get; set; }
public StateWalkLeft3 STATE_WALK_LEFT_3 { get; set; }
Is there a library or some other way I could use to partially parse only the STATE_0, STATE_1, etc fields? Could you maybe suggest a way to add these recently added JSON pairs?
Edited to clarify:
To get an idea of what I'm working with, here is the Class derived from the JSONs:
Check out my full Class to get an idea of what the JSONs contain
Basically, I just need a way to store these recently implemented chains in this class somehow for processing. All of those classes/properties are generated from these JSONs.
Use Newtonsoft Json.NET and as example following code
internal struct ChainX
{
public int x { get; set; }
public int isChain { get; set; }
}
static string json =
#"{
""STATE_WALK_LEFT"":{
""isChain"":""1"",
""x"":""1""
},
""STATE_WALK_LEFT_0"":{
""x"":""0""
},
""STATE_WALK_LEFT_1"":{
""x"":""40""
},
""STATE_WALK_LEFT_2"":{
""x"":""80""
},
""STATE_WALK_RIGHT"":{
""isChain"":""0""
},
""STATE_RUN_LEFT"":{
""isChain"":""0""
}
}";
and a line of code to deserialize to Dictionary:
var values = JsonConvert.DeserializeObject<Dictionary<string, ChainX>>(json);
after that you can simple access values by dictionary key:
ChainX valueWalkLeft1 = values["STATE_WALK_LEFT_1"];

Deserializing JSON using C#

Finding some difficulty in sourcing information in trying to deserialize JSON in C#.
I have results from Google custom search returned in JSON format. I just want to check through my steps and establish the order in trying to deserialize it. Is this right?
I need to create classes to match
the JSON format. Kind of like a
creating schema file.
Use the JavaScriptSerializer() class and
deserialize method to extract the
relevant bits.
One of the issues I think I am going to run into is that I don't require all of the data returned but only the html links. How can I achieve that?
UPDATE
I have updated my question with the following JSON snippet and C# code. I want to output the string 'links' to console but it doesn't seem to be working. I think I am defining my classes wrongly?
JSON from Google Custom Search
handleResponse({
"kind": "customsearch#search",
"url": {
"type": "application/json",
"template": "https://www.googleapis.com/customsearch/v1?q\u003d{searchTerms}&num\u003d{count?}&start\u003d{startIndex?}&hr\u003d{language?}&safe\u003d{safe?}&cx\u003d{cx?}&cref\u003d{cref?}&sort\u003d{sort?}&alt\u003djson"
},
"queries": {
"nextPage": [
{
"title": "Google Custom Search - lectures",
"totalResults": 9590000,
"searchTerms": "lectures",
"count": 1,
"startIndex": 2,
"inputEncoding": "utf8",
"outputEncoding": "utf8",
"cx": "017576662512468239146:omuauf_lfve"
}
],
"request": [
{
"title": "Google Custom Search - lectures",
"totalResults": 9590000,
"searchTerms": "lectures",
"count": 1,
"startIndex": 1,
"inputEncoding": "utf8",
"outputEncoding": "utf8",
"cx": "017576662512468239146:omuauf_lfve"
}
]
},
"context": {
"title": "Curriculum",
"facets": [
[
{
"label": "lectures",
"anchor": "Lectures"
}
],
[
{
"label": "assignments",
"anchor": "Assignments"
}
],
[
{
"label": "reference",
"anchor": "Reference"
}
]
]
},
"items": [
{
"kind": "customsearch#result",
"title": "EE364a: Lecture Videos",
"htmlTitle": "EE364a: \u003cb\u003eLecture\u003c/b\u003e Videos",
"link": "http://www.stanford.edu/class/ee364a/videos.html",
"displayLink": "www.stanford.edu",
"snippet": "Apr 7, 2010 ... Course materials. Lecture slides · Lecture videos (2008) · Review sessions. Assignments. Homework · Reading. Exams. Final exam ...",
"htmlSnippet": "Apr 7, 2010 \u003cb\u003e...\u003c/b\u003e Course materials. \u003cb\u003eLecture\u003c/b\u003e slides · \u003cb\u003eLecture\u003c/b\u003e videos (2008) · Review sessions. \u003cbr\u003e Assignments. Homework · Reading. Exams. Final exam \u003cb\u003e...\u003c/b\u003e",
"cacheid": "TxVqFzFZLOsJ"
}
]
}
);
C# Snippet
public class GoogleSearchResults
{
public string link { get; set; }
}
public class Program
{
static void Main(string[] args)
{
//input search term
Console.WriteLine("What is your search query?:");
string searchTerm = Console.ReadLine();
//concantenate the strings using + symbol to make it URL friendly for google
string searchTermFormat = searchTerm.Replace(" ", "+");
//create a new instance of Webclient and use DownloadString method from the Webclient class to extract download html
WebClient client = new WebClient();
string Json = client.DownloadString("https://www.googleapis.com/customsearch/v1?key=My Key&cx=My CX&q=" + searchTermFormat);
//create a new instance of JavaScriptSerializer and deserialise the desired content
JavaScriptSerializer js = new JavaScriptSerializer();
GoogleSearchResults results = js.Deserialize<GoogleSearchResults>(Json);
Console.WriteLine(results);
//Console.WriteLine(htmlDoc);
Console.ReadLine();
}
}
Thanks
I use your #2 approach: deserialize with the JavaScriptSerializer.
This is what I do to deserialize a response from Facebook:
// get the id for the uploaded photo
var jss = new JavaScriptSerializer();
var resource = jss.Deserialize<Facebook.Data.Resource>(responseText);
....where Facebook.Data.Resource is defined like this:
namespace Facebook.Data
{
public class Resource
{
public string id { get; set; }
}
}
The responseText that I am deserializing from looks like this:
{"id":"10150111918987952",
"from":{"name":"Someone",
"id":"782272221"},
"name":"uploaded from Cropper. (at 12\/15\/2010 7:06:41 AM)",
"picture":"http:\/\/photos-f.ak.fbcdn.net\/hphotos-ak-snc4\/hs817.snc4\/69790_101501113333332_782377951_7551951_8193638_s.jpg",
...
But since I have only one property defined in the Resource class, I only deserialize that. Define the fields in your class that you want to deserialize.
It works to use inheritance, of course. You can define your data classes like this:
namespace Facebook.Data
{
public class Resource
{
public string id { get; set; }
}
public class Person : Resource
{
public string name { get; set; }
}
}
...and then you can deserialize a Person object.
EDIT
Ok, given the sample json you provided in the updated question, here's how I wrote the classes to hold the response:
public class GoogleSearchItem
{
public string kind { get; set; }
public string title { get; set; }
public string link { get; set; }
public string displayLink { get; set; }
// and so on... add more properties here if you want
// to deserialize them
}
public class SourceUrl
{
public string type { get; set; }
public string template { get; set; }
}
public class GoogleSearchResults
{
public string kind { get; set; }
public SourceUrl url { get; set; }
public GoogleSearchItem[] items { get; set; }
// and so on... add more properties here if you want to
// deserialize them
}
And here's the C# code to deserialize:
// create a new instance of JavaScriptSerializer
JavaScriptSerializer s1 = new JavaScriptSerializer();
// deserialise the received response
GoogleSearchResults results = s1.Deserialize<GoogleSearchResults>(json);
Console.WriteLine(s1.Serialize(results));
Some comments:
The toplevel class to hold the search result is called GoogleSearchResults.
The first property in the GoogleSearchResults class is kind, corresponding to the first named property in the json object. You had link which isn't going to work, because link is not the name of a top-level property in that json object. There are properties lower in the hierarchy of your json named "link" but JavaScriptSerializer won't pull out those lower level things into the higher level.
The next property in my GoogleSearchResults class is of type SourceUrl. This is because the url property in the json is not a simple string - it is a json object with two properties, each with a string value. So SourceUrl as a class in C# gets two string properties, each with the appropriate name to deserialize one of those named properties.
the next property in the GoogleSearchResults class is called "items" so that it can deserialize the items dictionary from your json. Now items, as the name suggests, is an array in the json, as denoted by the square bracket around its value. This means there can be more than one item, although in your case there is just one item. So this property in C# must be an array (or collection). Each item in the json result is not a simple string, so, once again, as we did with SourceUrl, we need to define a holder class to deserialize the item object: GoogleSearchItem. This class has a bunch of simple string properties. The properties in the C# class could also be of type int or some other type, if that's what the json requires.
finally, when printing out the result, if you just call Console.WriteLine(result) you will see the result of the ToString() method that is implicitly invoked by Console.WriteLine. This will merely print the name of the type, in this case is "GoogleSearchResults", which is not what you want, I think. In order to see what's in the object, you need to serialize it, as I've shown. In the output of that, you will see only the values of things you deserialized. Using the classes I provided, the result will have less information than the original, because I didn't provide properties in the C# class corresponding to some of the json properties, so those weren't deserialized.
You could take a look at Json.NET and its LINQ support to create and query JSON. By crafting a nice LINQ query you will get only the stuff you need (you can select, group by, count, min, max, whatever you like).
http://msdn.microsoft.com/en-us/library/bb412170.aspx
http://msdn.microsoft.com/en-us/library/bb410770.aspx
Pull out the property you need after you have converted the JSON representation to a type in your C# app. I don't think there's a way to extract only one property from the JSON representation before you have converted it (though I am not sure).

Categories

Resources