System.Text.Json Serialize multiple objects/array - c#

Could someone help me. I'm having problem serializing multiple elements.
I'm getting this result which has multiple root elements.
[
{
"TITLE": "title1",
"Total EP": 16,
"Current EP": 1,
"URL": "https://www...",
}
]
[
{
"TITLE": "title2",
"Total EP": 16,
"Current EP": 2,
"URL": "https://www...",
}
]
[
{
"TITLE": "title3",
"Total EP": 16,
"Current EP": 3,
"URL": "https://www....",
}
]
How I can make the result like this? I don't want to have multiple objects. instead I want them merge in the same object.
[
{
"TITLE": "title",
"Total EP": 16,
"Current EP": 1,
"URL": "https://www...",
},
{
"TITLE": "title",
"Total EP": 16,
"Current EP": 2,
"URL": "https://www...",
},
{
"TITLE": "title",
"Total EP": 16,
"Current EP": 3,
"URL": "https://www....",
}
]
This is the code I'm using u
var total = root.Get("total")?.GetInt32();
var title = root.Get("title")?.GetString();
foreach (var url in root.Get("response")?.EnumerateArray()) {
var currentEp = url.Get("number")?.GetInt32();
var url = url.Get("url")?.GetString();
var options = new JsonWriterOptions {
Indented = true
};
using (var stream = new MemoryStream()) {
using (var writer = new Utf8JsonWriter(stream, options)) {
writer.WriteStartObject();
writer.WriteString("TITLE", title);
writer.WriteNumber("Total EP", total);
writer.WriteNumber("Current EP", currentEp);
writer.WriteString("URL", url);
writer.WriteEndObject();
}
string json = Encoding.UTF8.GetString(stream.ToArray());
Console.WriteLine(json);
}
}
Here's the example of json.
{
"pagination":{
"previous":null,
"next":null
},
"total":10,
"title": main title,
"response":[
{
"url":"https.....id1", //URL have different ids
"number":"1",
},
{
"url":"https.....id2",
"number":"2",
},
{
"url":"https.....id3",
"number":"3",
},
{
"url":"https.....id4",
"number":"4",
},
{
"url":"https.....id5",
"number":"5",
},
]
}
Thank you for the help.

Try this code
using (var stream = new MemoryStream())
{
var options = new JsonWriterOptions
{
Indented = true
};
using (var writer = new Utf8JsonWriter(stream, options))
{
writer.WriteStartArray();
for (int i = 0; i < 10; i++)
{
var currentEp = i;
var total = i;
var title = $"title{i}";
var url = $"url:{i}";
writer.WriteStartObject();
writer.WriteString("TITLE", title);
writer.WriteNumber("Total EP", total);
writer.WriteNumber("Current EP", currentEp);
writer.WriteString("URL", url);
writer.WriteEndObject();
}
writer.WriteEndArray();
}
string json2 = Encoding.UTF8.GetString(stream.ToArray());
Console.WriteLine(json2);
}

Related

C# bot framework Align checkboxes in adaptive card along a row

We have an adaptive card which is displayed after getting an answer from QnA. Within the card, we have choiceset displayed to let the user select the category he is interested in. Upon clicking select, the second level of options are given. However, we are planning to have the suboptions in the same card at first level. Is it possible to have checkboxes side by side in an adaptive card?
Code:
public List<Attachment> EmbedAdaptiveCategoryOptions()
{
#region populate choiceLists
List<AdaptiveChoice> OGChoice = new List<AdaptiveChoice>();
List<AdaptiveChoice> GeoChoice = new List<AdaptiveChoice>();
List<AdaptiveChoice> TechChoice = new List<AdaptiveChoice>();
List<AdaptiveChoice> ThemeChoice = new List<AdaptiveChoice>();
List<AdaptiveChoice> OKChoice = new List<AdaptiveChoice>();
List<string> OGids = new List<string>();
List<string> Geoids = new List<string>();
List<string> Techids = new List<string>();
List<string> themeids = new List<string>();
List<string> feedbackids = new List<string> { "I am good with the link already shared with me above!" };
List<CardAction> OGButtons = CreateOGButtons(out OGids);
foreach (var item in OGButtons)
{
OGChoice.Add(new AdaptiveChoice() { Title = item.Title, Value = item.Value.ToString() });
}
List<CardAction> GeoButtons = CreateGeoButtons(out Geoids);
foreach (var item in GeoButtons)
{
GeoChoice.Add(new AdaptiveChoice() { Title = item.Title, Value = item.Value.ToString() });
}
List<CardAction> techcardButtons = CreateTechButtons(out Techids);
foreach (var item in techcardButtons)
{
TechChoice.Add(new AdaptiveChoice() { Title = item.Title, Value = item.Value.ToString() });
}
List<CardAction> themecardButtons = CreateThemeButtons(out themeids);
foreach (var item in themecardButtons)
{
ThemeChoice.Add(new AdaptiveChoice() { Title = item.Title, Value = item.Value.ToString() });
}
List<CardAction> feedbackcardButtons = new List<CardAction>();
CardAction feedbackButton = new CardAction()
{
Value = "feedback",
Type = "imBack",
Title = "I am good with the link already shared with me above!"
};
feedbackcardButtons.Add(feedbackButton);
foreach (var item in feedbackcardButtons)
{
OKChoice.Add(new AdaptiveChoice() { Title = item.Title, Value = item.Value.ToString() });
}
#endregion
AdaptiveCard card = new AdaptiveCard();
List<Attachment> attachments = new List<Attachment>();
AdaptiveColumnSet Title = new AdaptiveColumnSet();
AdaptiveColumn titletext = new AdaptiveColumn();
titletext.Width = AdaptiveColumnWidth.Auto;
titletext.Items.Add(new AdaptiveTextBlock()
{
Weight = AdaptiveTextWeight.Bolder,
Wrap = true,
Text = "Are you interested in searching through the file? Please select the Category you would like to refine Credentials for:",
Size = AdaptiveTextSize.Medium
});
Title.Columns.Add(titletext);
card.Body.Add(Title);
AdaptiveColumnSet abc = new AdaptiveColumnSet();
AdaptiveColumn col1 = new AdaptiveColumn();
col1.Width = AdaptiveColumnWidth.Auto;
col1.Type = "TextBlock";
col1.Items.Add(new AdaptiveChoiceSetInput()
{
Choices = OGChoice,
Separator = true,
IsMultiSelect = true,
Type = "Input.ChoiceSet"
});
AdaptiveColumn col2 = new AdaptiveColumn();
col2.Width = AdaptiveColumnWidth.Auto;
col2.Type = "TextBlock";
//col2.Type = AdaptiveTextBlock.TYPE;
col2.Items.Add(new AdaptiveChoiceSetInput()
{
Choices = GeoChoice,
Separator = true,
IsMultiSelect = true,
Type = "Input.ChoiceSet"
});
AdaptiveColumn col3 = new AdaptiveColumn();
col3.Width = AdaptiveColumnWidth.Auto;
col3.Type = "TextBlock";
//col2.Type = AdaptiveTextBlock.TYPE;
col3.Items.Add(new AdaptiveChoiceSetInput()
{
Choices = TechChoice,
Separator = true,
IsMultiSelect = true,
Type = "Input.ChoiceSet"
});
AdaptiveColumn col4 = new AdaptiveColumn();
col4.Width = AdaptiveColumnWidth.Auto;
col4.Type = "TextBlock";
//col2.Type = AdaptiveTextBlock.TYPE;
col4.Items.Add(new AdaptiveChoiceSetInput()
{
Choices = ThemeChoice,
Separator = true,
IsMultiSelect = true,
Type = "Input.ChoiceSet"
});
AdaptiveColumn col5 = new AdaptiveColumn();
col5.Width = AdaptiveColumnWidth.Auto;
col5.Type = "TextBlock";
//col2.Type = AdaptiveTextBlock.TYPE;
col5.Items.Add(new AdaptiveChoiceSetInput()
{
Choices = OKChoice,
Separator = true,
IsMultiSelect = true,
Type = "Input.ChoiceSet"
});
abc.Columns.Add(col1);
abc.Columns.Add(col2);
abc.Columns.Add(col3);
abc.Columns.Add(col4);
abc.Columns.Add(col5);
card.Body.Add(abc);
List<AdaptiveAction> Actions = new List<AdaptiveAction>()
{
new AdaptiveSubmitAction()
{
Id = "selectBtn",
Title = "Select",
Speak = "<s>Search</s>",
DataJson = "{ \"Type\": \"SubmitQuestion\" }"
}
};
card.Actions.Add(Actions[0]);
Attachment attachment = new Attachment()
{
ContentType = AdaptiveCard.ContentType,
Content = card
};
attachments.Add(attachment);
return attachments;
}
You can align check boxes side-by-side in an AdaptiveCard by placing them in columns. Take a look at the AdaptiveCards documentation on columns and see the example below.
Screenshot
AdaptiveCard JSON
{
"type": "AdaptiveCard",
"body": [
{
"type": "TextBlock",
"horizontalAlignment": "Center",
"size": "Medium",
"text": "Horizontal Checkboxes",
"maxLines": 3
},
{
"type": "ColumnSet",
"separator": true,
"columns": [
{
"type": "Column",
"items": [
{
"type": "Input.Toggle",
"id": "option1",
"title": "Option 1",
"value": "true"
}
],
"width": "auto"
},
{
"type": "Column",
"items": [
{
"type": "Input.Toggle",
"id": "option2",
"title": "Option 2",
"value": "false"
}
],
"width": "auto"
},
{
"type": "Column",
"items": [
{
"type": "Input.Toggle",
"id": "option3",
"title": "Option 3",
"value": "true"
}
],
"width": "auto"
},
{
"type": "Column",
"items": [
{
"type": "Input.Toggle",
"id": "option4",
"title": "Option 4",
"value": "false"
}
],
"width": "auto"
}
]
}
],
"actions": [
{
"type": "Action.Submit",
"title": "Submit"
}
],
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"version": "1.0"
}
Also, I would recommend using the AdaptiveCard Designer to help format and create your cards.
Hope this helps!

JSON - LINQ Query for object or an array to group two data with same key value pair

Consider I have a JSON data as:
{
"entities":[
{
"republish": false,
"OrgID": "",
"createdby": "730",
"questions": [
{
"sequence": "5",
"QuestionId": "57BB6DDC-A90A-10EE-E224-EC658A825871",
"metadata": [
{
"key": "Group",
"value": 0
},
{
"key": "Part",
"value": "0"
}
]
},
{
"sequence": "4",
"QuestionId": "57BB6DDC-A90A-10EE-E224-EC658A825871",
"metadata": [
{
"key": "Group",
"value": 1
},
{
"key": "Part",
"value": "A"
}
]
},
{
"sequence": "3",
"QuestionId": "57BB6DDC-A90A-10EE-E224-EC658A825871",
"metadata": [
{
"key": "Group",
"value": 1
},
{
"key": "Part",
"value": "B"
}
]
}
]
}
]
}
As you can see I have a list of questions available and in each question, I have a metadata which holds Key-Value pair.
Above example demonstrates, I have 3 questions and out of it 2 question, metadata key-value is "Group 1".
Now I want to do is combine the questions with a same key-value pair and treat it as one.
so in my final case, I will have 2 questions instead of 3. And out of that one question will have two separate questions inside.
And I want to achieve this using Linq query. And if possible please use Newtonsoft for parse if needed. I have been stuck for long onto this.
Things I have done:
public virtual HttpResponseMessage AddQuestionsToStandardMaster(TaxonomyMetaData objQuestion)
{
List<ResponseEntity> objResponseList = new List<ResponseEntity>();
try
{
if (ModelState.IsValid)
{
foreach (var objEntity in objQuestion.Entities)
{
EntityResponse objentityresponse = new EntityResponse();
ResponseEntity objResponse = new ResponseEntity();
}
List<Question> objQuestionList = new List<Question>();
if (objEntity.Questions.Length > 0)
{
foreach (var item in objEntity.Questions)
{
int questionTypeid = 0;
dynamic objQuestionJson = JObject.Parse(item.ToString())
}
}
}
Question objCurrentQuestion = new Question();
Question objQuestionforDelete = new Question();
JObject itemToParese = new JObject();
string SingleQuestionJson = objQuestionJson.GetValue("QuestionData").ToString();
string questionstem = "";
Regex rgx = new Regex("/\'");
objCurrentQuestion.Sequence = Convert.ToInt32(objQuestionJson.GetValue("sequence"));
objCurrentQuestion.tag = objQuestionJson.tag.ToObject<JToken[]>(); ;
objCurrentQuestion.metadata = objQuestionJson.metadata.ToObject<JToken[]>();
objCurrentQuestion.SingleQuestionJson = rgx.Replace(SingleQuestionJson, "'");
objCurrentQuestion.QuestionsType = questionTypeid;
objCurrentQuestion.QuestionsId = new Guid(objQuestionJson.GetValue("QuestionId").ToString());
objCurrentQuestion.VersionNo = Convert.ToInt32(objQuestionJson.GetValue("VersionNo"));
objCurrentQuestion.DisplayQuestionId = Convert.ToString(objQuestionJson.GetValue("DisplayQuestionId"));
objCurrentQuestion.OriginalQuestionId = Convert.ToString(objQuestionJson.GetValue("OriginalQuestionId"));
objCurrentQuestion.PassageText = Convert.ToString(objQuestionJson.GetValue("passage_text"));
objCurrentQuestion.PassageCode = Convert.ToString(objQuestionJson.GetValue("passage_id"));
objCurrentQuestion.PassageTitle = Convert.ToString(objQuestionJson.GetValue("passage_title"));
objCurrentQuestion.IsPublished = Convert.ToByte(true);
objCurrentQuestion.ProductId = objEntity.ProductID;
foreach (var metadata in objCurrentQuestion.metadata)
{
switch (metadata["key"].ToString())
{
case "Group":
objCurrentQuestion.Group = Convert.ToInt32(metadata["value"].ToString());
break;
case "Part":
objCurrentQuestion.Part = metadata["value"].ToString();
break;
}
}
objQuestionList.Add(objCurrentQuestion);
int counter = 1;
//Here I get the data in a group which needs to coverted to JSOn and then replace the original JSON data with this. But I know this is irrelevant to what we need to achieve.
var yui = objQuestionList.Where(tma => tma.Group == counter).Select(t => t).GroupBy(s => new { s.Group }).Where(p => p.Count() > 1).ToList();
//After proper conversion I need to enter this data to a database.
I am a bit unclear on what do you mean by make it
combine the questions with a same key-value pair and treat it as one
But here is how you can group by the JSON into groups in metadata you can do a custom select to what ever you want.
var text = #"{
""entities"":[
{
""republish"": false,
""OrgID"": """",
""createdby"": ""730"",
""questions"": [
{
""sequence"": ""5"",
""QuestionId"": ""57BB6DDC-A90A-10EE-E224-EC658A825871"",
""metadata"": [
{
""key"": ""Group"",
""value"": 0
},
{
""key"": ""Part"",
""value"": ""0""
}
]
},
{
""sequence"": ""4"",
""QuestionId"": ""57BB6DDC-A90A-10EE-E224-EC658A825871"",
""metadata"": [
{
""key"": ""Group"",
""value"": 1
},
{
""key"": ""Part"",
""value"": ""A""
}
]
},
{
""sequence"": ""3"",
""QuestionId"": ""57BB6DDC-A90A-10EE-E224-EC658A825871"",
""metadata"": [
{
""key"": ""Group"",
""value"": 1
},
{
""key"": ""Part"",
""value"": ""B""
}
]
}
]
}
]
}";
var json = JObject.Parse(text);
var groupedData = from entity in json["entities"]
from question in entity["questions"]
group question by question["metadata"][0]["value"] into questionGroup
select questionGroup;
foreach (var data in groupedData)
{
Console.WriteLine("_____________________");
Console.WriteLine("Group");
Console.WriteLine(data.Key);
foreach (var question in data)
{
Console.WriteLine(question["QuestionId"]);
}
Console.WriteLine("_____________________");
}
If "Group" is not always the fist item in the array you can do
question["metadata"].First(md => md.Value<string>("key") == "Group")["value"]
to get it.

Get chrome bookmarks from json

I want to scrape chrome bookmarks using json object. What I want to do is get all bookmarks from 1 folder. That is the structure of the json:
{
"checksum": "d499848083c2c2e3a38f547da4cbad7c",
"roots": {
"bookmark_bar": {
"children": [ {
"children": [ {
"url": "https://www.example.com/"
}, {
"url": "https://www.another-example.com/"
} ],
"name": "foo",
} ],
"name": "Menu bookmarks",
},
"other": {
"name": "Another bookmarks",
},
"synced": {
"name": "Phone bookmarks",
}
},
"version": 1
}
In this case I want to get urls from folder foo. I am using Json.NET to convert string into object. This code:
string input = File.ReadAllText(bookmarksLocation);
using (StringReader reader = new StringReader(input))
using (JsonReader jsonReader = new JsonTextReader(reader)) {
JsonSerializer serializer = new JsonSerializer();
var o = (JToken)serializer.Deserialize(jsonReader);
var allChildrens = o["roots"]["bookmark_bar"]["children"];
var fooFolder = allChildrens.Where(x => x["name"].ToString() == "foo");
foreach (var item in fooFolder["children"]) {
Console.WriteLine(item["url"].ToString());
}
Console.ReadKey();
}
Is giving me an error:
Cannot apply indexing with [] to an expression of type 'IEnumerable<JToken>'
Can you tell me what I did wrong?
there is 1 loop is missing:
var fooFolder = allChildrens.Where(x => x["name"].ToString() == "foo");
foreach (var folder in fooFolder)
{
foreach (var item in folder["children"])
{
Console.WriteLine(item["url"].ToString());
}
}

Delete JSON Data inside Property based on ID in C#

I have a requirement to delete the data inside JSON file. I have tried so many way but it is not deleting the data. I have also tried this example.
Remove JSON objects from a large file
But in above example they are passing a jsonstring but I have a jobject type of data.
My JSON File is as following.
{
"id": 123,
"name": "Pankaj Kumar",
"address": {
"street": "El Camino Real",
"city": "San Jose",
"zipcode": 95014
},
"experiences": [
{
"companyid": 1,
"companyname": "abc1"
},
{
"companyid": 20,
"companyname": "Genpact Headstrong"
},
{
"companyid": 71,
"companyname": "new company"
},
{
"companyid": 77,
"companyname": "Mind Tree LTD"
},
{
"companyid": 89,
"companyname": "TCS"
},
{
"companyid": 22,
"companyname": "Hello World LTD"
}
],
"phoneNumber": 9988664422,
"role": "Developer"
}
I want to delete company based on companyid.
I have tried following code to delete based on company id.
private void DeleteCompany() {
var json = File.ReadAllText(jsonFile);
try {
var jObject = JObject.Parse(json);
JArray experiencesArrary = (JArray) jObject["experiences"];
Console.Write("Enter Company ID to Delete Company : ");
var companyId = Convert.ToInt32(Console.ReadLine());
if (companyId > 0) {
var companyName = string.Empty;
foreach(var company in experiencesArrary.Where(obj => obj["companyid"].Value < int > () == companyId)) {
companyName = Convert.ToString(company["companyname"]);
}
var companyToDeleted = "{ 'id': " + companyId + ", 'companyname': '" + companyName + "'}";
experiencesArrary.Remove(companyToDeleted);
jObject["experiences"] = experiencesArrary;
string output = Newtonsoft.Json.JsonConvert.SerializeObject(jObject, Newtonsoft.Json.Formatting.Indented);
File.WriteAllText(jsonFile, output);
} else {
Console.Write("Invalid Company ID, Try Again!");
UpdateCompany();
}
} catch (Exception) {
throw;
}
}
Please suggest or modify my code which delete the data.
There is no need for creating deleteObject like you are doing, you are very close to solution.You can simply find your object like this and remove.
var companyToDeleted = experiencesArrary.Where(obj => obj["companyid"].Value<int>() == companyId).ToList();
foreach (var item in companyToDeleted)
{
experiencesArrary.Remove(item);
}
Update
var companyToDeleted = experiencesArrary.FirstOrDefault(obj => obj["companyid"].Value<int>() == companyId);
experiencesArrary.Remove(companyToDeleted);

Newtonsoft JSON - create JArray in JArray

I am trying to create JSON array using Newtonsoft JSON API but its giving me error. I want to achieve structure like
[
{
"id":"26",
"appsurvey":"1",
"fk_curriculumid":"70",
"status":"Completed",
"lastaccessedon":"2014-06-20 09:18:54",
"questions":[
{
"feedback":"6",
"questionid":"1"
},
{
"feedback":"8",
"questionid":"2"
},
{
"feedback":"1",
"questionid":"3"
}
],
"fk_clientid":"24",
"learnerid":"260"
}
]
I want ot add questions array for multiple time but it is giving me error
Can not add property questions to Newtonsoft.Json.Linq.JObject. Property with the same name already exists on object.
Here is my code:
JArray surveytrackingA = new JArray();
/*code to add
[
{"id":"26",
"appsurvey":"1",
"fk_curriculumid":"70",
"status":"Completed",
"lastaccessedon":"2014-06-20 09:18:54"}]
*/
for (int i = 0; i < surveytrackingA.Count; i++)
{
JObject surveytrackD = (JObject)surveytrackingA[i];
string queryOne = "select * from table101 where fk_curriculumid='"
+ surveytrackD["fk_curriculumid"].ToString()
+ "' and fk_surveyid='"
+ surveytrackD["appsurvey"].ToString() + "'";
JArray questionsA = new JArray();
using (var stmt = await App.localDB.PrepareStatementAsync(queryOne))
{
while (await stmt.StepAsync())
{
JObject questionD = new JObject();
questionD.Add("questionid", stmt.GetTextAt(5));
questionD.Add("feedback", stmt.GetTextAt(6));
questionsA.Add(questionD);
}
}
surveytrackD.Add("questions", questionsA); /*error occurred here when second question array is getting inserted in surveyTrackD*/
surveytrackingA.Add(surveytrackD);
}
Can anyone please correct me. Thanks in advance.
Update:
surveytrackD have the json data,
{
"fk_clientid": "24",
"learnerid": "260",
"appsurvey": "1",
"id": "26",
"fk_curriculumid": "70",
"status": "completed",
"lastaccessedon": "2014-06-20 09:18:54"
}
You can achieve the same result (JArray in JArray) using regular C# classes and at the end serialize to JSon.
I posted a sample in Github; here a fragment of the code that produces your expected output:
var Surveys = new List<SurveytrackD>();
Surveys.Add( new SurveytrackD { id = "26", appsurvey = "1", fk_curriculumid = "70", status = "Completed", learnerid = "240" } );
Surveys.Add( new SurveytrackD { id = "27", appsurvey = "1", fk_curriculumid = "71", status = "Completed", learnerid = "241" });
foreach (var survey in Surveys)
{
survey.questions = new List<Question>();
survey.questions.Add(new Question { questionid = "1", feedback = "0" });
survey.questions.Add(new Question { questionid = "2", feedback = "1" });
}
var json = JsonConvert.SerializeObject(Surveys, Formatting.Indented);
Console.WriteLine(json);
The output is:
[
{
"fk_clientid": null,
"learnerid": "240",
"appsurvey": "1",
"id": "26",
"fk_curriculumid": "70",
"status": "Completed",
"lastaccessedon": null,
"questions": [
{
"feedback": "0",
"questionid": "1"
},
{
"feedback": "1",
"questionid": "2"
}
]
},
{
"fk_clientid": null,
"learnerid": "241",
"appsurvey": "1",
"id": "27",
"fk_curriculumid": "71",
"status": "Completed",
"lastaccessedon": null,
"questions": [
{
"feedback": "0",
"questionid": "1"
},
{
"feedback": "1",
"questionid": "2"
}
]
}
]

Categories

Resources