retrive specific data from nested json string - c#

I have a block of JSON as follows:
{
"FirstName": "JON",
"LastName": "BAYN",
"Data": [
{
"Plan": "DAY"
}
]
}
I have built it using JavaScriptSerializer like
JavaScriptSerializer serializer_user = new JavaScriptSerializer();
dynamic jsonObject = serializer_user.Deserialize<dynamic>(content_);
dynamic firstname = jsonObject["FirstName"];
firstname = jsonObject["FirstName"];
But I am not able to read from nested "Details" >> "Plan". I've been unable to piece together how to accomplish this goal.

At first, make model class to your json schema:
public class Rootobject
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Gender { get; set; }
public int MemberID { get; set; }
public Detail[] Details { get; set; }
}
public class Detail
{
public string Plan { get; set; }
public string Product { get; set; }
public DateTime ProductStartDate { get; set; }
public DateTime ProductEndDate { get; set; }
public string Flag { get; set; }
}
Now you can deserialize your json string to RootObject (Use Json.NET instead of JavaScriptSerializer because it is faster etc):
using Newtonsoft.Json;
..
// If Json.NET is not option:
// var obj = new JavaScriptSerializer().Deserialize<Rootobject>(json)
var obj = JsonConvert.DeserializeObject<Rootobject>(json);
And now you are able to access object structure like following:
if (obj.Details != null)
{
foreach (var detail in obj.Details)
{
Console.WriteLine(detail.Plan);
}
}

If you don't want to create new classes for it and deserialize it, you could just do a regex.

Related

How to get data value in string C#

I have an object like this. How can I parse the Name Surname from this object?
Object
{
"HasError":false,
"AlertType":"success",
"AlertMessage":"Operation has completed successfully",
"ModelErrors":[],
"Data":{
"Count":1,
"Objects":
[{
"Id":291031530,
"FirstName":"Alp",
"LastName":"Uzan",
"MiddleName":"",
"Login":"alp"
}]
}
}
I'm getting this data to an external api using HttpClient but I can't parse it by values. Can you help with this, the type of data is System.String
You have a couple of options. The most type-safe way would be to define C# classes which represent the schema of your JSON content and then deserialise into an instance of those like so:
public class Data
{
public int Count { get; set; }
public List<DataObject> Objects { get; set; }
}
public class DataObject
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string MiddleName { get; set; }
public string Login { get; set; }
}
public class MyJSONObject
{
public bool HasError { get; set; }
public string AlertType { get; set; }
public string AlertMessage { get; set; }
public Data Data { get; set; }
}
...
//Deserialise
var json = "<snip>";
var deserialised = JsonSerializer.Deserialize<MyJSONObject>(json);
//Extract the info you want
Console.WriteLine(deserialised.Data.Objects[0].LastName);
A second, more quick and dirty way to do it would be to parse the JSON into a JsonObject (this is using System.Text.Json) and then extract out the info you need:
var jsonObj = JsonObject.Parse(Properties.Resources.JSON);
var objectsArray = ((JsonArray)y["Data"]["Objects"]);
Console.WriteLine(objectsArray[0]["LastName"]);
A similar method would work with Newtonsoft.Json as well, although you'd need to use JObject instead of JsonObject and JArray rather than JsonArray in that case.
If you use c#, save output in string and serialize, usa this library
using Newtonsoft.Json;
JObject json = JObject.Parse(str);
string Name= json.Data.Objects[0].FirstName
string Surname = json.Data.Objects[0].Lastname
If you are using System.Text.Json:
var jsonObject= JsonSerializer.Deserialize<JsonObject>(jsonString);
Then you can use jsonObject["Data"]["Objects"][0]["FirstName"] to get the data.

How to display JSON data (nested) in C#

I am fetching an API that returns a JSON response like this:
{
"id": 161635,
"rev": 1,
"fields": {
"System.Url": "http://google.com",
"System.Type": "Bug",
"System.State": "New",
"System.AssignedTo": {
"displayName": "John Doe"
}
}
}
I want to display the id and everything inside fields.
This is my model:
public class WorkItemDetail {
public int id { get; set; }
public Dictionary<string, object> fields {get;set;}
}
Here is the problem, I can display the id and everything in fields except for some reason, I can't show displayName
Here is what I doing:
#WorkItemDetailResponse.id
#WorkItemDetailResponse.fields["System.WorkItemType"];
#WorkItemDetailResponse.fields["System.State"];
#WorkItemDetailResponse.fields["System.AssignedTo"];
#WorkItemDetailResponse.fields["System.AssignedTo"]["displayName"]; <!-- does not work -->
#code{
WorkItemDetailResponse = JsonConvert.DeserializeObject<WorkItemDetail>(ResponseBody);
}
I am new to C# so I don't know why this line is not working
#WorkItemDetailResponse.fields["System.AssignedTo"]["displayName"]
Create your DTO structure as follows:
public class Fields
{
[JsonProperty("System.Url")]
public string SystemUrl { get; set; }
[JsonProperty("System.Type")]
public string SystemType { get; set; }
[JsonProperty("System.State")]
public string SystemState { get; set; }
[JsonProperty("System.AssignedTo")]
public SystemAssignedTo SystemAssignedTo { get; set; }
}
public class WorkItemDetail
{
public int id { get; set; }
public int rev { get; set; }
public Fields fields { get; set; }
}
public class SystemAssignedTo
{
public string displayName { get; set; }
}
here's fiddle: https://dotnetfiddle.net/F9Wppv
another way - using dynamic variable: https://dotnetfiddle.net/Goh7YY
You need to cast the object value to a JObject
((JObject)JsonConvert.DeserializeObject<WorkItemDetail>(json).fields["System.AssignedTo"])["displayName"]
JSON.Net will create a JObject if the property type is object and the value is a JSON object.
db<>fiddle

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");
}

Deserialize JSON using specific properties

I'm trying to deserialize JSON without declaring every property in C#. Here is a cut-down extract of the JSON:
{
"resourceType": "export",
"type": "search",
"total": 50,
"timestamp": "2020-08-02T18:26:06.747+00:00",
"entry": [
{
"url": "test.com/123",
"resource": {
"resourceType": "Slot",
"id": [
"123"
],
"schedule": {
"reference": {
"value": "testvalue"
}
},
"status": "free",
"start": "2020-08-03T08:30+01:00",
"end": "2020-08-03T09:00+01:00"
}
}
]
}
I want to get the values out of entry → resource, id and start.
Any suggestions on the best way to do this?
I've made very good experiences with json2sharp. You can enter your JSON data there and it will generate the classes you need to deserialize the JSON data for you.
public class Reference
{
public string value { get; set; }
}
public class Schedule
{
public Reference reference { get; set; }
}
public class Resource
{
public string resourceType { get; set; }
public List<string> id { get; set; }
public Schedule schedule { get; set; }
public string status { get; set; }
public string start { get; set; }
public string end { get; set; }
}
public class Entry
{
public string url { get; set; }
public Resource resource { get; set; }
}
public class Root
{
public string resourceType { get; set; }
public string type { get; set; }
public int total { get; set; }
public DateTime timestamp { get; set; }
public List<Entry> entry { get; set; }
}
The next step is to choose a framework which will help you to deserialize. Something like Newtonsoft JSON.
Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse);
If you want to get the data without declaring classes, you can use Json.Net's LINQ-to-JSON API (JToken, JObject, etc.). You can use the SelectToken method with a JsonPath expression to get what you are looking for in a couple of lines. Note that .. is the recursive descent operator.
JObject obj = JObject.Parse(json);
List<string> ids = obj.SelectToken("..resource.id").ToObject<List<string>>();
DateTimeOffset start = obj.SelectToken("..resource.start").ToObject<DateTimeOffset>();
Working demo here: https://dotnetfiddle.net/jhBzl4
If it turns out there are actually multiple entries and you want to get the id and start values for all of them, you can use a query like this:
JObject obj = JObject.Parse(json);
var items = obj["entry"]
.Children<JObject>()
.Select(o => new
{
ids = o.SelectToken("resource.id").ToObject<List<string>>(),
start = o.SelectToken("resource.start").ToObject<DateTimeOffset>()
})
.ToList();
Demo: https://dotnetfiddle.net/Qe8NB7
I am not sure why you don't deserialize the lot (even if it's minimally populated) since you have to do the inner classes anyway.
Here is how you could bypass some of the classes (1) by digging into the JObjects
Given
public class Reference
{
public string value { get; set; }
}
public class Schedule
{
public Reference reference { get; set; }
}
public class Resource
{
public string resourceType { get; set; }
public List<string> id { get; set; }
public Schedule schedule { get; set; }
public string status { get; set; }
public string start { get; set; }
public string end { get; set; }
}
public class Entry
{
public string url { get; set; }
public Resource resource { get; set; }
}
You could call
var results = JObject.Parse(input)["entry"]
.Select(x => x.ToObject<Entry>());

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.

Categories

Resources