Read and parse Json on c# and get specific values - c#

I'm trying to parse a Json that contains a lot of objects.
.json look like this:
:
{
"status" : "success",
"prices" : [
{
"market_hash_name" : "4X4 Car",
"price" : "7.87",
"created_at" : 1472587613
},
{
"market_hash_name" : "Yellow Car",
"price" : "27.75",
"created_at" : 1472519899
}
[...] etc
and I just want to get the price of specific market hash name. How can I do that?
I have got this atm
using System.IO;
using Newtonsoft.Json;
public class MarketHandler
{
//Methods
public MarketHandler updatePrices()
{
var json = File.ReadAllText("PriceSkins.json");
currentPrices = JsonConvert.DeserializeObject<Data>(json);
return this;
}
public Data currentPrices { get; set; }
public class Data
{
public Response response { get; set; }
}
public class Response
{
public string status { get; set; }
public Price prices { get; set; }
}
public class Price
{
public string market_hash_name { get; set; }
public string price { get; set; }
public int created_at { get; set; }
}

You can do like this, place your JSON some where else on your system and load the JSON like below
Rootobject ro = new Rootobject();
StreamReader sr = new StreamReader(Server.MapPath("text.json"));
string jsonString = sr.ReadToEnd();
JavaScriptSerializer ser = new JavaScriptSerializer();
ro = ser.Deserialize<Rootobject>(jsonString);
Before that you have to create the classes like below these classes are matching your JSON, already I have answer similar this question here you can cehck how to create classes for JSON easily
public class Rootobject
{
public string status { get; set; }
public Price[] prices { get; set; }
}
public class Price
{
public string market_hash_name { get; set; }
public string price { get; set; }
public int created_at { get; set; }
}
After that,from the instance of the Rootobject(ro) you can access the price like below
Price[] price_list = ro.prices;

Related

deserialize API response with different json value in the result

I'm querying an external service and wanted to deserialize the response into a customer object but the issue is response for each customer may be different. some customer may have Sales entity in the response and few may have Marketing.
The json property for sales entity is SalesId and for marketing is MarketingId. Can you advise whether the model I use to store result is correct or any improvement ? If so, how would I deserialize the response without knowing the correct json property ?
For Customer 66666
{
"customerId": "66666",
"customerName": "test1234",
"dependentEntity": [
{
"SalesId": "3433434",
"SalesPersonName": "343434",
"SaleSource": "StorePurchase"
}
]
}
For Customer 5555
{
"customerId": "55555",
"customerName": "test2",
"dependentEntity": [
{
"MarketingId": "3433434",
"MarketingAppName": "343434",
"MarketingSource": "Online"
}
]
}
Here is the Model I'm thinking but not sure the correct one
public class Customer
{
public string customerId { get; set; }
public string customerName { get; set; }
public IList<T> dependentList { get; set; }
}
public class Dependent
{
[JsonProperty("Id")]
public string Id { get; set; }
public string Name { get; set; }
public string Source { get; set; }
}
You could probably try something like the following one:
public class DependentEntity
{
[JsonProperty("SalesId")]
public string SalesId { get; set; }
[JsonProperty("SalesPersonName")]
public string SalesPersonName { get; set; }
[JsonProperty("SaleSource")]
public string SaleSource { get; set; }
[JsonProperty("MarketingId")]
public string MarketingId { get; set; }
[JsonProperty("MarketingAppName")]
public string MarketingAppName { get; set; }
[JsonProperty("MarketingSource")]
public string MarketingSource { get; set; }
}
public class Customer
{
[JsonProperty("customerId")]
public string CustomerId { get; set; }
[JsonProperty("customerName")]
public string CustomerName { get; set; }
[JsonProperty("dependentEntity")]
public IList<DependentEntity> DependentEntity { get; set; }
}
We have a type for DependentEntity that has both the attributes of Marketing and Sales object. After parsing your input, you could create a logic (checking the attributes) based on which you could check if a DependentEntity is a Marketing or a Sales object.
The above classes was generated using, jsonutils.
If we can assume that the dependentEntity contains only a single type of objects then you can use json.net's schema to perform branching based on the matching schema.
So, lets suppose you have these dependent entity definitions:
public class DependentMarket
{
public string MarketingId { get; set; }
public string MarketingAppName { get; set; }
public string MarketingSource { get; set; }
}
public class DependentSales
{
public string SalesId { get; set; }
public string SalesPersonName { get; set; }
[JsonProperty("SaleSource")]
public string SalesSource { get; set; }
}
...
Then you can use these classes to generate json schemas dynamically:
private static JSchema marketSchema;
private static JSchema salesSchema;
//...
var generator = new JSchemaGenerator();
marketSchema = generator.Generate(typeof(DependentMarket));
salesSchema = generator.Generate(typeof(DependentSales));
And finally you can do the branching like this:
var json = "...";
var semiParsedJson = JObject.Parse(json);
JArray dependentEntities = (JArray)semiParsedJson["dependentEntity"];
JObject probeEntity = (JObject)dependentEntities.First();
if (probeEntity.IsValid(marketSchema))
{
var marketEntities = dependentEntities.ToObject<List<DependentMarket>>();
...
}
else if (probeEntity.IsValid(salesSchema))
{
var salesEntities = dependentEntities.ToObject<List<DependentSales>>();
...
}
else if ...
else
{
throw new NotSupportedException("The provided json format is not supported");
}

How to generate a JSON class with dynamic name

I don't know if there is an existing name for that case, but I'm trying to retrieve data from NASA API (https://api.nasa.gov/) and I have a simple challenge to catch a list of objects near earth. Here is the JSON response I have from the GET request I do to "https://api.nasa.gov/neo/rest/v1/feed?...."
{
"links": {
"next": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-07-04&end_date=2021-07-04&detailed=false&api_key=NjgpxgSbYHXyFSBI3HaOhRowtjMZgAKv2t4DMRym",
"prev": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-07-02&end_date=2021-07-02&detailed=false&api_key=NjgpxgSbYHXyFSBI3HaOhRowtjMZgAKv2t4DMRym",
"self": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-07-03&end_date=2021-07-03&detailed=false&api_key=NjgpxgSbYHXyFSBI3HaOhRowtjMZgAKv2t4DMRym"
},
"element_count": 6,
"near_earth_objects": {
"2021-07-03": [
{
"links": {
"self": "http://www.neowsapp.com/rest/v1/neo/3701710?api_key=NjgpxgSbYHXyFSBI3HaOhRowtjMZgAKv2t4DMRym"
},
"id": "3701710",
"neo_reference_id": "3701710",
"name": "(2014 WF497)",
"nasa_jpl_url": "http://ssd.jpl.nasa.gov/sbdb.cgi?sstr=3701710",
"absolute_magnitude_h": 20.23,
"estimated_diameter": {
"kilometers": {
}
And that's the way it is built in Visual Studio (using the Special Paste option for JSON)
public class NearEarthObject
{
public Links links { get; set; }
public int element_count { get; set; }
public Near_Earth_Objects near_earth_objects { get; set; }
}
public class Links
{
public string next { get; set; }
public string prev { get; set; }
public string self { get; set; }
}
public class Near_Earth_Objects
{
public _20210703[] _20210703 { get; set; }
}
public class _20210703
{
public Links1 links { get; set; }
public string id { get; set; }
public string neo_reference_id { get; set; }
public string name { get; set; }
public string nasa_jpl_url { get; set; }
public float absolute_magnitude_h { get; set; }
public Estimated_Diameter estimated_diameter { get; set; }
public bool is_potentially_hazardous_asteroid { get; set; }
public Close_Approach_Data[] close_approach_data { get; set; }
public bool is_sentry_object { get; set; }
}
The question is, inside of the element "near_earth_objects", there is an element called "2021-07-03" (the date of the data I requested), the problem is that I am trying to include it into a DataGridView made in .NET C# (Windows Forms, but that doesn't matters here, I think) and the user wants to get the information by date. So, "2021-07-03" is a valid member just for one day, and the user should be able to get data from multiple days.
So, is there a way in C# to get all child objects inside of near_earth_objects without knowing their names since there will be the option to search for asteroids from date X to Y in my application?
Using System.Text.Json
The API response will map to the following classes
public class Neo
{
public Links Links { get; set; }
public int ElementCount { get; set; }
public Dictionary<string, List<NearEarthObject>> NearEarthObjects { get; set; }
}
public class Links
{
public string Next { get; set; }
public string Prev { get; set; }
public string Self { get; set; }
}
public class NearEarthObject
{
public Links Links { get; set; }
public string Id { get; set; }
public string Name { get; set; }
// Other properties
}
The NearEarthObjects is simply a Dictionary, where the key is the formatted date and value is a List containing NearEarthObject
The PropertyNamingPolicy will allow us to support the API's underscore property naming convention.
public class UnderscoreNamingPolicy : JsonNamingPolicy
{
public override string ConvertName(string name)
{
return name.Underscore();
}
}
Example usage
// using using System.Text.Json;
var response = await new HttpClient().GetStringAsync(url);
var neo = JsonSerializer.Deserialize<Neo>(response, new JsonSerializerOptions
{
PropertyNamingPolicy = new UnderscoreNamingPolicy()
});
foreach(var neos in neo.NearEarthObjects)
{
Console.WriteLine(neos.Key);
}
use System.Text.Json, JsonNamingPolicy
demo code
public class DynamicNamePolicy : JsonNamingPolicy
{
public override string ConvertName(string name)
{
var today = DateTime.Today.ToString("yyyy-MM-dd");
if (name.Equals("DateData")) //model property name
return today; //convert to json string property name
return name;
}
}
//data deserialize
string data = ""; //json string
var obj = JsonSerializer.Deserialize<NearEarthObject>(data, new JsonSerializerOptions
{
PropertyNamingPolicy = new DynamicNamePolicy(),
});

how to get data from json in c#?

I Get json data from third party in json format.
I am trying to fetch RollId from "Id" and MType from "Data" in some cases
"Data" doesn't have fields it is kind of blank.
It's working when we have "Data". In case of blank it's not working.
any idea on this? Is there a better approach of doing this?
This is the Json
string json = #"{
'root': {
'_type': '_container',
'Class': '.key.PModel',
'Elements': {
'_type': 'array<element>',
'_data': [
{
'_type': 'element',
'Class': '.key.PElement',
'Id': {
'_type': 'testId',
'Class': '.key.PModel',
'RollId': '.key.7157'
},
'Data': {
'_type': 'p_model',
'Class': '.key.Unsupported',
'MType': '.TestMType',
'Version': {
'_type': 'test__version',
'Class': '.key.TestVersion',
}
}
},
{
'_type': 'element',
'Class': '.key.PElement',
'Id': {
'_type': 'TestId',
'Class': '.key.PModel',
'RollId': '.key.11261'
},
'Data': '.ref.root.Elements.0.Data'
},
{
'_type': 'element',
'Class': '.key.PElement',
'Id': {
'_type': 'TestId',
'Class': '.key.PModel',
'RollId': '.key.7914'
},
'Data': '.ref.root.Elements.0.Data'
}
]
}
}
}";
This is the Code
public class Program
{
static void Main(string[] args)
{
//it provide json
var testCont = thirdpartyapi();
var dataList = new List<TestResponse>();
foreach (var testData in testCont.Elements())
{
var data = new TestResponse();
data.col1 = Convert.ToInt32(testData.Id().RollId());
data.col2 = testData.Data().MType().ToString();
dataList.Add(data);
}
}
public class TestResponse
{
public int col1 { get; set; }
public string col2 { get; set; }
}
}
First, try to get a valid well-formed json. You can use this code beautify tool. Then you can automatically generate C# class using json2csharp. Finally as you have C# class you can apply if statements and check if property is null.
Generated C# wrapper:
public class Id
{
public string _type { get; set; }
public string Class { get; set; }
public string RollId { get; set; }
}
public class Datum
{
public string _type { get; set; }
public string Class { get; set; }
public Id Id { get; set; }
public object Data { get; set; }
}
public class Elements
{
public string _type { get; set; }
public List<Datum> _data { get; set; }
}
public class Root
{
public string _type { get; set; }
public string Class { get; set; }
public Elements Elements { get; set; }
}
public class RootObject
{
public int encoding_version { get; set; }
public Root root { get; set; }
}
If you want to pick only few fields from complex JSON, you can consider using Cinchoo ETL - an open source library
Sample below shows how to pick RollId and MType values from your json
using (var r = new ChoJSONReader("## YOUR JSON FILE PATH ##")
.WithJSONPath("$.._data")
.WithField("RollId", jsonPath: "$..Id.RollId", fieldType: typeof(string))
.WithField("MType", jsonPath: "$..Data.MType", fieldType: typeof(string))
)
{
foreach (var rec in r)
{
Console.WriteLine((string)rec.RollId);
Console.WriteLine((string)rec.MType);
}
}
Hope it helps.
The easiest way is use the DataContractJsonSerializer
Here you can read more about it.
All in all you need to create a model which has the same possible outcome as your json.
Then you can just use the DataContractJsonSerializer to create an object of you model by using a MemoryStream.
Here you can find a nice tool to create the model from the JSON.
For example this one:
public class Id
{
public string _type { get; set; }
public string Class { get; set; }
public string RollId { get; set; }
}
public class Datum
{
public string _type { get; set; }
public string Class { get; set; }
public Id Id { get; set; }
public object Data { get; set; }
}
public class Elements
{
public string _type { get; set; }
public List<Datum> _data { get; set; }
}
public class Root
{
public string _type { get; set; }
public string Class { get; set; }
public Elements Elements { get; set; }
}
public class RootObject
{
public int encoding_version { get; set; }
public Root root { get; set; }
}
Then you use the MemoryStream and the DataContractJsonSerializer to Create an object of RootObject from that JSON.
MemoryStream stream1 = new MemoryStream();
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(RootObject));
stream1.Position = 0;
RootObject rootObject = (RootObject)ser.ReadObject(stream1);
And yes, as Adriani6 mentiones - your JSON is invalid at this point:
"Data": {
"_type": "p_model",
"Class": ".key.Unsupported",
"MType": ".TestMType",
"Version": {
"_type": "test__version",
"Class": ".key.TestVersion",
}
There is a , at the end wich is not allowed.

How to set up class for json?

I am working with opentdb.com api and have no idea how to access data in this json:
{
"response_code":0,
"results": [
{
"category":"Animals",
"type":"multiple",
"difficulty":"easy",
"question":"What is the scientific name for modern day humans?",
"correct_answer":"Homo Sapiens",
"incorrect_answers":[
"Homo Ergaster",
"Homo Erectus",
"Homo Neanderthalensis"
]
},
{
"category":"Entertainment: Cartoon & Animations",
"type":"multiple",
"difficulty":"easy",
"question":"Who voices for Ruby in the animated series RWBY?",
"correct_answer":"Lindsay Jones",
"incorrect_answers":[
"Tara Strong",
"Jessica Nigri",
"Hayden Panettiere"
]
}
]
}
I am using Newtonsoft.Json and i tried this with only 1 Question but im geting an error that says that key value is wrong..
class Trivia
{
public Trivia(string json)
{
JObject jObject = JObject.Parse(json);
JToken jresults = jObject["results"];
category = (string)jresults["category"];
type = (string)jresults["type"];
difficulty = (string)jresults["difficulty"];
question = (string)jresults["question"];
correct_answer = (string)jresults["correct_answer"];
incorrect_answers = jresults["incorrect_answers"].ToArray();
}
public string category { get; set; }
public string type { get; set; }
public string difficulty { get; set; }
public string question { get; set; }
public string correct_answer { get; set; }
public Array incorrect_answers { get; set; }
}
Copy from json text and in new class in visual studio Edit-->Paste Special-->Paste JSON As Classes
public class Rootobject
{
public int response_code { get; set; }
public Result[] results { get; set; }
}
public class Result
{
public string category { get; set; }
public string type { get; set; }
public string difficulty { get; set; }
public string question { get; set; }
public string correct_answer { get; set; }
public string[] incorrect_answers { get; set; }
}
using namespace
using Newtonsoft.Json;
response is value get from your service
var outdeserialized = JsonConvert.DeserializeObject<Rootobject>(response);

Structure of Json in C#

My Goal:
Read JSON from site, get values of certain items and display them, after I successfully
pull that off I will want to implement taking in a value like true and set it to false.
For starters I need help figuring out how to read and write the variables. I have read
lots of tutorials and blogs about how to read in the data and parse it but what isn't
explained is where is the value stored?
Like I have this http://elsite.com/.json and it has this:
{
dola: "p9", data:{
house: [{
dola: "p9", data:{
owner: "blah", // string
price: blah, // int
url: "http://www.link.com", // url/string
message: "blahblah",
checked: false
}
},
{
dola: "p9", data:{
owner: "blah", // same as above
I have built this to get the data:
[DataContract]
class container
{
[DataMember(Name = "data")]
public Data1 dataStart { get; set; }
[DataContract]
public class Data1
{
[DataMember(Name = "house")]
public HouseA[] home { get; set; }
[DataContract]
public class HouseA
{
[DataMember(Name = "data")]
public Data2 dataSec { get; set; }
[DataContract]
public class Data2
{
[DataMember(Name = "owner")]
public string own { get; set }
[DataMember(Name = "message")]
public strinng mess { get; set; }
}
}
}
}
I want to use
var blah = from post in container.dataStart.house.data // obviously not the right way to do it
select new MessageItem
{
User = post.own,
Meza = post.mess
}
with
public class MessageItem
{
public string User;
public string Meza;
}
So basically it boils down to I am not COMPLETELY understanding the structure of the arrays and objects.
Anyone able to guide me in the right way to do the from.in.select?
Have you looked at Json.NET http://json.codeplex.com/ which includes LINQ to JSON support
I prefer JavaScriptSerializer (System.Web.Extensions.dll) for this; the following works:
JsonResult obj = new JavaScriptSerializer().Deserialize<JsonResult>(json);
var qry = from house in obj.data.house
let post = house.data
select new MessageItem
{
User = post.owner,
Meza = post.message
};
with:
class JsonResult
{
public string dola { get; set; }
public Data data { get; set; }
public class Data
{
public List<House> house { get; set; }
}
public class House
{
public string dola { get; set; }
public HouseData data { get; set; }
}
public class HouseData
{
public string owner { get; set; }
public int price {get;set;}
public Uri url {get;set;}
public string message {get;set;}
public bool #checked {get;set;}
}
}

Categories

Resources