c# Web api nested json field change dynamically - c#

I need to return a json object from my web api. The problem is there is a nested object. in that object column name changed dynamically and also nested object has only cursive bracket. Sample json given below. Any one know how to solve this issue please help.
[
{
src: 'https://www.test.com/line.jpg',
screen: 'PLAYLIST_SCREEN',
data: {
playlist_id: '751becbe-5546-4728-8738-e96238be4749'
}
},
{
src: 'https://www.test.com/linet-2.jpg',
screen: 'VIDEO_SCREEN',
data: {
video_id: '40541a11-e29d-4852-91c8-c2aac76d64c9'
}
},
{
src: 'https://www.test.com/line_3xl.jpg?impolicy=HomeHero',
screen: 'SEARCH_SCREEN',
data: {
query: 'برنامج صباح الخير يا كويت'
}
}
]

Assuming data is coming from a C# object, you can use this attribute to skip serialization of any properties that are null:
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
Here is an example of what data might look like in C#:
public class data
{
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonPropertyName("playlist_id")]
public string? PlaylistId { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonPropertyName("video_id")]
public string? VideoId { get; set; }
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
[JsonPropertyName("query")]
public string? Query { get; set; }
};
The Microsoft documentation has more examples of usage.

Related

How to serialize this C# return value into a JSON object?

I have this object value that is being returned and I would like to convert it into a useful JSON object that I can inspect and manipulate. Ultimately, my goal is to validate the values of username and accessKey. But 2 things are throwing this off. Double {{ makes it invalid JSON and sauce:options can't be converted into a property in a class.
{{
"browserName": "MicrosoftEdge",
"browserVersion": "latest",
"platformName": "Windows 10",
"sauce:options": {
"username": "test",
"accessKey": "123"
}
}}
Here is what I tried:
string output = JsonConvert.SerializeObject(SauceSession.Options.ConfiguredEdgeOptions);
This SauceSession.Options.ConfiguredEdgeOptions returns that object I mentioned above.
Got this back:
Newtonsoft.Json.JsonSerializationException: 'Error getting value from 'BinaryLocation' on 'OpenQA.Selenium.Edge.EdgeOptions'.'
I also tried this as per suggestions:
var serialized = JsonConvert.SerializeObject(SauceSession.Options.ConfiguredEdgeOptions);
And got back this Newtonsoft.Json.JsonSerializationException: 'Error getting value from 'BinaryLocation' on 'OpenQA.Selenium.Edge.EdgeOptions'.'
Since you cannot fix the source, you're going to have to apply a bodge to fix the JSON, for example this will work:
var fixedJson = sourceJson.Substring(1, Json.Length - 2);
Now you should have a couple of classes to hold your data, this way you can also cope with the unusual names:
public class Root
{
public string BrowserName { get; set; }
public string BrowserVersion { get; set; }
public string PlatformName { get; set; }
[JsonProperty("sauce:options")]
public Options SauceOptions { get; set; }
}
public class Options
{
public string Username { get; set; }
public string AccessKey { get; set; }
}
And now you should be able to deserialise like this:
var root = JsonConvert.DeserializeObject<Root>(fixedJson);

Deserialize JSON array of values in C#

I've got some difficulties with this json script:
{
"insured_agent_flag": "a",
"id": "1",
"agent": {
"fullName": "John Travolta",
"mobileNumberPdf": "+987654321",
"mobileNumber": "",
"identityCard": {
"identityCardExpirationDate": null
},
"secondIdentityCard": {
"identityCardExpirationDate": null
},
"notes": {},
"sign": "ADVANCED"
},
"basicData": {
"personType": "PERSON",
"agreeWithCompleteAnalysis": false,
"investmentInterest": false
},
"nonOfferedProducts": [
"PROD_A",
"PROD_B",
"PROD_C"
]
}
I would like to get some parameters from this script and put it into sql server table.
In order to do that, I used and transformed a C# script shared by https://mycontraption.com:
using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using System.Web.Script.Serialization;
using Microsoft.SqlServer.Dts.Pipeline;
namespace SC_c7e2d8c3918d46a5a07a1b438ddc7642
{
public class BasicData
{
public string agreeWithCompleteAnalysis { get; set; }
public string inOtherSystem { get; set; }
public string investmentInterest { get; set; }
}
public class ParentObject
{
public BasicData BasicData { get; set; }
public int id { get; set; }
public string insured_agent_flag { get; set; }
public IEnumerable<string> NonOfferedProducts { get; set; }
}
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
JavaScriptSerializer js = new JavaScriptSerializer();
// Give the input column a variable to make it easier to reference.
BlobColumn combinedColumn = Row.parameterscon;
// Convert from blob to string
string reviewConverted = System.Text.Encoding.ASCII.GetString(combinedColumn.GetBlobData(0, Convert.ToInt32(combinedColumn.Length)));
// Deserialize the string
ParentObject obj = js.Deserialize<ParentObject>(reviewConverted);
var rows = obj.NonOfferedProducts.ToList();
Row.agreeWithCompleteAnalysis = obj.BasicData.agreeWithCompleteAnalysis;
Row.inOtherSystem = obj.BasicData.inOtherSystem;
Row.investmentInterest = obj.BasicData.investmentInterest;
Row.projectionid = obj.id;
Row.insuredagentflag = obj.insured_agent_flag;
//Row.nonOfferedProducts =
}
}
}
For 'standard' objects it works fine, but there is a problem with array "nonOfferedProducts". After compiling I get an error:
„object reference not set to an instance of an object”.
Here are my questions:
1. How should I handle 'nonOfferedProducts' array in C# script?
2. Why do I get foregoing error?
3. Unfortunately there exists a possibility, that json scripts would have some errors, like missing braces. How should I handle that?
Thank you!
Thanks a lot for your answers. According to your comments I'll try to give you more explanations:
1. The json script I have added in this post - it's only small part of whole script. In complete script there is a lot of different parameters. What is more, my C# code should scan about 40.000 json scripts (stored in sql server table in one column). These scripts has got similiar structure - but not the same.
So I thought about C# resolution, that will be searching for the parameters that I need. For json scripts without these parameters the c# code will put nulls to the right output columns.
Here are my output columns:
-agreeWithCompleteAnalysis
-inOtherSystem
-investmentInterest
-projectionId
-insuredAgentFflag
-nonOfferedProducts
I understood, that structure of my classes were wrong - I'll improve that.
But I've got one doubt - is it possible to prepare c# code structure, that will handle only these parameters I need?
And finally, I would like to put the results into my database.
For example if nonOfferedProducts property will have 3 values (not always!), I'd like to send to my database table 3 records (3 different values for nonOfferedProducts column and 3 the same values for the rest columns -agreeWithCompleteAnalysis, inOtherSystem etc).
I hope that will be clear now.
Thanks a lot for your help!
J
Use https://quicktype.io and paste json, it will generate c# model and serializer code.
As I said in my comment, your c# model doesn't match the JSON object.
If the model was made up of various nested objects to better reflect the actual JSON then you'll have more luck:
public class IdentityCard
{
public DateTime? IdentityCardExpirationDate { get; set; }
}
public class Notes
{
//No idea what should be in here...
}
public class BasicData
{
public string PersonType { get; set; }
public bool AgreeWithCompleteAnalysis { get; set; }
public bool InvestmentInterest { get; set; }
}
public class Agent
{
public string FullName { get; set; }
public string MobileNumberPdf { get; set; }
public string MobileNumber { get; set; }
public IdentityCard IdentityCard { get; set; }
public IdentityCard SecondIdentityCard { get; set; }
public Notes Notes { get; set; }
public string Sign { get; set; }
}
//Note: THIS is the actual class that matches the JSON sample given.
public class ParentObject
{
public string insured_agent_flag { get; set; }
public int Id { get; set; }
public Agent Agent { get; set; }
public BasicData BasicData { get; set; }
public IEnumerable<string> NonOfferedProducts { get; set; }
}
Once the model is correct, then Deserialization works fine for me with the given example (I did this in a unit test, but assuming your string matches your example this should be fine)
//get json
string json = #"
{
""insured_agent_flag"": ""a"",
""id"": ""1"",
""agent"": {
""fullName"": ""John Travolta"",
""mobileNumberPdf"": ""+987654321"",
""mobileNumber"": """",
""identityCard"": {
""identityCardExpirationDate"": null
},
""secondIdentityCard"": {
""identityCardExpirationDate"": null
},
""notes"": {},
""sign"": ""ADVANCED""
},
""basicData"": {
""personType"": ""PERSON"",
""agreeWithCompleteAnalysis"": false,
""investmentInterest"": false
},
""nonOfferedProducts"": [
""PROD_A"",
""PROD_B"",
""PROD_C""
]
}";
var js = new JavaScriptSerializer();
ParentObject obj = js.Deserialize<ParentObject>(json);
//do things...
var rows = obj.NonOfferedProducts.ToList();
Assert.AreEqual(3, rows.Count);
Assert.AreEqual("PROD_A", rows.First());
The asserts pass - This code happily gets the list of strings in the NonOfferedProducts property with the given example.
Obviously if you cannot rely on the consistency of the JSON (either structure or how well-formed it is) then you'll have problems, but that's a different issue.
To answer your question no 2) you are getting the object reference error because the BasicDataClass.nonOfferedProducts is null and you are trying iterate over it , this may be a reason that you are sending the wrong json which JavaScriptSerializer is not able to deserilize.
your 3rd question you can always validate your json with json validators which are there online like https://jsonformatter.org/

How to Deserialize JSON data? C#

Im getting a Json Data from an API and i have been trying to deserialize.
Json data:
{
   "items": [
      {
         "id": "1",
         "name": "samplename",
         "AddressList1": {
            "City": "Hyd",
            "State": "TN",
            "Country": "IN"
         },
         "Age": "10"
      },
      {
         "id": "2",
         "name": "samplename2",
         "AddressList1": {
            "City": "Hydd",
            "State": "TN",
            "Country": "IN"
         },
         "Age": "10"
      }
   ],
   "paging": {
      "cursors": {}
   }
}
Entities:
public class AddressList1
{
public string City { get; set; }
public string State { get; set; }
public string Country { get; set; }
}
public class Item
{
public string id { get; set; }
public string name { get; set; }
public AddressList1 addressList1 { get; set; }
public string Age { get; set; }
}
public class Cursors
{
}
public class Paging
{
public Cursors cursors { get; set; }
}
public class Users
{
public List<Item> items { get; set; }
public Paging paging { get; set; }
}
C# code:
JsonConvert.DeserializeObject<List<Users>>(content);
Error Message:
Cannot deserialize the current JSON object (e.g. {"name":"value"})
into type 'System.Collections.Generic.List`1[Entities.Users]'
because the type requires a JSON array (e.g. [1,2,3]) to deserialize
correctly.
where am i doing wrong?
The following is a JSON-object; in your case a User
{ ... }
The following is a JSON-array; in your case an array of User
[ { ... }, { ... } ]
Thus if you want to deserialize the JSON you got into an array of Users this is not possible because you have no array in JSON.
Therefore the right code to deserialize is:
JsonConvert.DeserializeObject<Users>(content);
Furthermore your mapping is erroneous because in JSON there is a property AddressList1 and in the class it is called addressList1
Given your JSON, you would need a POCO object that contains a items member and a paging member.
JsonConvert.DeserializeObject<Users>(content);
should work.
Your Json string is good formatted and the entities are according to Json2Csharp good too.
but your problem is with the instruction JsonConvert.DeserializeObject<List<Users>>(content);
all that json that you have is only ONE User, and you are trying to get a list of them, there is the issue,
you can try instead with:
JsonConvert.DeserializeObject<Users>(content);
Try Below Code
JsonConvert.DeserializeObject<Users>(content);
Your entities(models) look just fine. If you are using, or were to use ASP.NET Web API 2, and your client is using the http verb post for example, this setup would work as Web API takes care of the object deserialization:
public HttpStatusCode Post(Item item)
{
Debug.Write(item.toString());
return HttpStatusCode.OK;
}
If you insist in deserializing manually then use the JavaScriptSerializer library which allows you to do things like:
Item item = new JavaScriptSerializer().Deserialize<Item>(content);
Notice that .Deserialize<T>() takes a generic which in your case it Item.
Hope that helps.

write data from JSON in C#

I have JSON like this:
{
'surveys': [
{
'title': 'first',
'id': 100,
},
{
'title': 'second',
'id': 101,
},
{
'title': 'third',
'id': 102,
},
]
}
I want to have the output like this:
title: first
title: second
title: third
and my program in C# is like this:
WebClient client = new WebClient();
var json = client.DownloadString("http://www.test.com/api/surveys/?api_key=123");
Debug.WriteLine(json); //write all data from json
//add
var example = JsonConvert.DeserializeObject<Example>(json);
Debug.WriteLine(example.Data.Length);
class Example
{
public surveys[] Data { get; set; }
}
class surveys
{
public string title { get; set; }
public int id { get; set; }
}
I get this error:
Thrown: "Object reference not set to an instance of an object." (System.NullReferenceException) Exception Message = "Object reference not set to an instance of an object.", Exception Type = "System.NullReferenceException", Exception WinRT Data = ""
at this line: Debug.WriteLine(example.Data.Length);
where is the problem?
One problem I see is that your outer class has a property named Data, which is an array of 'surveys' objects, but your Json has a list of 'surverys' objects under the property 'surveys'. Hence the 'Data' property is never populated.
Consider the following C# class structure:
class Example
{
public survey[] surveys{ get; set; }//Data renames to surveys
}
class survey //Singular
{
public string title { get; set; }
public int id { get; set; }
}
Why can't you do so?:
JObject data = JObject.Parse(json);
foreach (var survey in data["surveys"].Children())
{
Debug.WriteLine("title: " + survey["title"]);
}
You need to use JSON.Net and use the class JsonConvert and the method DeserializeObject<T>.
If you run this:
JsonConvert.DeserializeObject<JObject>();
Then you will get back a list of de-serialized JObject objects.
Use, NuGet to download the package. I think it is called JSON.net.
Here is the weblink
WebClient client = new WebClient();
var json = client.DownloadString("http://www.test.com/api/surveys/?api_key=123");
Debug.WriteLine(json); //write all data from json
//add
var example = JsonConvert.DeserializeObject<Survey>(json);
Debug.WriteLine(example.length); // this could be count() instead.
class Survey
{
public string title { get; set; }
public int id { get; set; }
}
This should work!
Use json2csharp to generate c# classes from json.
You will also need to use Json.NET.
public class Survey
{
public string title { get; set; }
public int id { get; set; }
}
public class RootObject
{
public List<Survey> surveys { get; set; }
}
Then you can do:
var client = new WebClient();
string json = client.DownloadString(some_url);
RootObject root = JsonConvert.DeserializeObject<RootObject>(json);
foreach (Survey s in root.surveys)
{
// Do something with your survey
}
Don't forget to use Newtonsoft.Json namespace once you add a reference to it within your project.
using Newtonsoft.Json;
Edit: I have tested it using:
string json = "{'surveys': [{'title': 'first','id': 100,},{'title': 'second','id': 101,},{'title': 'third','id': 102,},]}";
instead of using the WebClient, and it works.

Parsing JSON data in C#

I have a JSON data as follows
{"id": "367501354973","from": {
"name": "Bret Taylor",
"id": "220439" }
which is returned by an object(result) of IDictionary[String, Object]
In my C# code:
I have made a class for storing the JSON value which is as follows
public class SContent
{
public string id { get; set; }
public string from_name { get; set; }
public string from_id { get; set; }
}
My main C# function which stores the parses the JSON data and stores the value inside the class properties is as follows:
List<object> data = (List<object>)result["data"];
foreach (IDictionary<string, object> content in data)
{
SContent s = new SContent();
s.id = (string)content["id"];
s.from_name = (string)content["from.name"];
s.from_id = (string)content["from.id"];
}
When i execute this code, i get an exception saying System cannot find the Key "from.name" and "from.id"
When i comment the two lines (s.from_name = (string)content["from.name"];s.from_id = (string)content["from.id"];) my code runs fine.
I think i am not able to refer the nested JSON data properly.
Can anyone just validate it and please tell me how to refer nested data in JSON in C#?
Thanks
I'm not sure how you are parsing the JSON string. Are you using a class in the Framework to do the deserialization?
You could use the JavaScriptSerializer Class defined in the System.Web.Script.Serialization Namespace (you may need to add a reference to System.Web.dll)
Using that class, you would write your code like this:
public class SContent
{
public string id { get; set; }
public SFrom from { get; set; }
}
public class SFrom
{
public string name { get; set; }
public string id { get; set; }
}
Then deserialization looks like this:
var json = new JavaScriptSerializer();
var result = json.Deserialize<SContent>(/*...json text or stream...*/);
See JavaScriptSerializer on MSDN. You might also want to check out this similar question.

Categories