Unable to iterate Jobject when having single value - c#

I am using for each to iterate and get values of a json object in my solution.
Let me give example of the json.
[
{
"#Seq": "1",
"#text": "123456789"
},
{
"#Seq": "2",
"#text": "abc"
},
{
"#Seq": "3",
"#text": "xyz"
}
]
It works well for multiple sequences until we have only one seq in the json.
example:
{{
"#Seq": "1",
"#text": "123456789"
}}
Coming to Code:
foreach (var installinst in atpmessage["AUTOPILOTMessage"]["AUTOPILOTBody"]["OrderHeader"]["InstallationInstructions"]["InstallationInstruction"])
{
responseISGEMEA.data.install_instruct =installinst["#text"].ToString();
}
The installinst in the loop gives me just the Seq. Not the text.
{"#Seq": "1"}
how do I make it work with single and multiple sequences.

Related

How to access inner properties of a Json Object?

I am learning C# and I am trying to parse json/xml responses and check each and every key and value pair. For xml I am converting to json so I have only one function/script to work with both cases. My issue is that I am working with a wide range of json responses which are not similar and there may be arrays in some of the json response. I have tried accessing the "Count" of the json object as a way to check for arrays.
Note: The responses will vary. This example is for Products > Product > name, quantity and category. The next response will change and can be like Country > State > Cities and so on. I cannot rely on creating classes since all responses are going to be different. Plus I am working on automating it so it should be able to handle anything thrown at it.
Sample Json I am working with:
{
"products": {
"product": [
{
"name": "Dom quixote de La Mancha",
"quantity": "12",
"category": "Book"
},
{
"name": "Hamlet",
"quantity": "3",
"category": "Book"
},
{
"name": "War and Peace",
"quantity": "7",
"category": "Book"
},
{
"name": "Moby Dick",
"quantity": "14",
"category": "Book"
},
{
"name": "Forrest Gump",
"quantity": "16",
"category": "DVD"
}
]
}
The way I am accessing the count, name and value is as follows:
dynamic dyn = JsonConvert.DeserializeObject<dynamic>(jsonText);
foreach (JProperty property in dyn.Properties())
{
string propname = property.Name;
var propvalue = property.Value;
int count = property.Count;
}
Is there a way to access these without going through the foreach loop like int count = dyn.Count ? All I am getting from this is null instead of actual values.
For the above example my end result will be like:
This responses contains products> product> 5 x (name, quantity, category)
The QuickWatch for the object:
QuickWatch for dyn object
Try to deserialize your JSON into JObject like below:
var jObject = JsonConvert.DeserializeObject<JObject>(jsonText);

C# How to combine multiple JSON arrays that are part of a List?

What has been done so far?
I am working on dividing up the number of records into 3 batches and processing them in parallel to increase the performance. However, after processing the batches in parallel I would also like to save the outcome (JSON string) of the processed records in a variable.
As you can see below, I first initialize the variable as List of string and then run the foreach loop which saves the processed outcome as mentioned below.
List<string> responseOutcome = new List<string>();
Parallel.ForEach(recordBatches, batch => {
responseOutcome.Add(response1.Content);
});
Result in List responseOutcome comes as:
responseOutcome[0]
[
{
"Name": "Sample1",
"ID": "123"
},
{
"Name": "Sample2",
"ID": "394"
}
],
responseOutcome[1]
[
{
"Name": "Sample5",
"ID": "384"
},
{
"Name": "Sample6",
"ID": "495"
}
],
responseOutcome[2]
[
{
"Name": "Sample3",
"ID": "473"
},
{
"Name": "Sample4",
"ID": "264"
}
]
What I would like to achieve?
Now I would like to take the value of responseOutcome which is multiple arrays of JSON string and merge them into one big JSON string.
Final Output
[
{
"Name": "Sample1",
"ID": "123"
},
{
"Name": "Sample2",
"ID": "394"
},
{
"Name": "Sample5",
"ID": "384"
},
{
"Name": "Sample6",
"ID": "495"
},
{
"Name": "Sample3",
"ID": "473"
},
{
"Name": "Sample4",
"ID": "264"
}
]
I looked into several similar cases but they weren't nearly similar. Like:
How do I merge multiple json objects
How do I combine two arrays from two JObjects in Newtonsoft JSON.Net?
Any help/guidance will be great!!
Using Newtonsoft, you can create a JArray from each of your responses. Then you can flatten the hierarchy using linq's SelectMany method and re-serialize the object.
Try this:
var obj = responses.Select(r => JArray.Parse(r.Trim(','))).SelectMany(token => token);
string json = JsonConvert.SerializeObject(obj, Formatting.Indented);
There are probably more efficient ways to do this if you want to do pure string manipulation, but using Newtonsoft, I would deserialize, merge and then re-serialize.
Create a small POCO model:
public class ResponseOutcomeModel
{
public string ID { get; set; }
public string Name { get; set; }
}
Then deserialize to this model, merge and reserialize to JSON as a single list.
var outcomeList = new List<ResponseOutcomeModel>();
foreach (var i in responseOutcome)
{
outcomeList.AddRange(JsonConvert.DeserializeObject<List<ResponseOutcomeModel>>(i.Trim().TrimEnd(',')));
}
var finalJson = JsonConvert.SerializeObject(outcomeList);
Note, the Time/TrimEnd is used if the trailing commas in your example are really there in your responseOutcome array (at the end of each element in the array). The call to DeserializeObject will complain if you leave the commas in there.

Convert JSON [][] to object in c#

I have a little problem converting my JSON Object I have to something I can work within C# code.
{ "CheckboxHours": {
"method": "ID",
"valueparts": [
"Hour",
[ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23" ]
]
}
}
This is my JSON String I have, which is for creates me the Selenium Object.
What i want is to combine the values from valueparts[0] ("Hour") with valueparts[1][0-23] with each other and create an array of Selenium Objects
var jsonData = JsonConvert.DeserializeObject<jsonc#file>(_jsonFile);
Object[] hours = (Object[])jsonData.CheckboxHours.Valueparts[1];
SeleniumCheckBox[] checkbox = new SeleniumCheckBox[hours.Length];
for (int i = 0; i < hours.Length; ++i)
{
cbHour[i] = new SeleniumCheckBox(jsonData.CheckboxHours.Valueparts[0].ToString() + hours[i]);
}
The SeleniumCheckBox is a Class I made which just takes the value and creates in the background a new Selenium Element with findElement(By.ID(value)). This is working already.
My Problem here is that he doesn't allow the Conversion from jsonData to Object[] and I don't really know how I can handle this.
I hope it is clear what I want to have - if not feel free to ask for more specific data.
I think. You can try this.
var jsonData = JsonConvert.DeserializeObject<dynamic>(_jsonFile);
var hours = jsonData.CheckboxHours.valueparts[1];
foreach (var hour in hours)
{
//Some code
}
I am not sure if I understood everything correctly, but the reason for failure in deserialization might be that valueparts is List parameter, usually in c# the Lists contain only 1 type of parameters eg. string, or int. In your case, "Hour" (valueparts[0]) is a string, and valueparts[1] is List. I assume here is the conflict with deserializing the JSON string.
{
CheckboxHours:{
"method":"ID",
"valueparts":{
Measure: "Hour",
MesureValues:
[
"0","1","2","3","4","5","6","7",
"8","9","10","11","12","13","14",
"15","16","17","18","19","20",
"21","22","23"
]
}
}
}
Change valueparts to object, as in the code above, so you can use Hour as string and the values as List.

Serialize/Deserialize nested objects in flat structure

I'm sure that somewhere there is a simple answer to my question, but I couldn't fin it. The problem I faced is following, I have code structure:
class Field
{
List<Block> Blocks {get;set;}
public static Field CreateField()
{
var A = new Block {Connector = new Connector()}
var B = new Block {Connector = new Connector()}
A.Connector.ConnectedTo.Add(B);
B.Connector.ConnectedTo.Add(A);
var field = new Field();
field.Blocks = new List {A, B};
return field;
}
}
class Block
{
Connector Connector {get;set;}
}
class Connector
{
List<Block> ConnectedTo {get;set;}
}
Than serialization command using json.net:
JsonConvert.SerializeObject(Field.CreateField(), Formatting.Indented, new JsonSerializerSettings {PreserveReferencesHandling = PreserveReferencesHandling.Objects});
and output result is as expected:
{
"$id": "1",
"Blocks": [
{
"$id": "2",
"Connector": {
"$id": "3",
"ConnectedTo": [
{
"$id": "4",
"Connector":{
"$id": "5",
"ConnectedTo": [
{
"$ref": "2"
}
]
}
}
]
}
}
]
}
Is there any way to have serialization result as following:
{
"$id": "1",
"Blocks": [
{
"$id": "2",
"Connector": {
"$id": "3",
"ConnectedTo": [
{
"$ref": "4"
}
]
}
},
{
"$id": "4",
"Connector":{
"$id": "5",
"ConnectedTo": [
{
"$ref": "2"
}
]
}
}
]
}
Thanks.
No. In your second example, $ref : 4 points to an $id that occurs later in the JSON. Json.Net will not be able to deserialize this-- when it comes upon a $ref it expects to be able to resolve it to an $id that it has already seen.
I would recommend against requiring users modify JSON directly anyway unless they are technically savvy. As I've seen from answering many JSON-related questions on SO, it is very easy to get the format messed up if you edit it manually-- missing quotes or commas, mismatched braces, invalid syntax, you name it. What will you do when someone screws it up? I think a better option is to make a tool that allows manipulating your structure abstractly. The tool could deserialize the original JSON, allow certain changes and then reserialize it into the new structure. Users would not need to know anything about the underlying JSON format that way.

Add data array into existing property

I've tried different solutions but I'm not reaching anywhere.
I'm in a middle of a loop and sometimes I need to add data to an existing property (details in this case).
So, in the beginning I create the following JObject without any problem:
var json = JsonConvert.SerializeObject(
new {
details = new[]{
new{product_name = detail["product_name"].ToString(),
quantity = detail["quantity"].ToString(),
product_options = detail["product_options"].ToString()},
}
}
);
// _elements is an dictionary<int, JObject>
_elements.Add(id, JObject.Parse(json));
// output
{
"details": [
{
"product_name": "Oranges",
"quantity": "2",
"product_options": [],
}
]
}
But, for some reason, I need to add more products to the list of details, so I would like my output to be:
{
"details": [
{
"product_name": "Oranges",
"quantity": "2",
"product_options": [],
},
{
"product_name": "Coca Cola",
"quantity": "5",
"product_options": [],
}
]
}
I've tried so far without any success:
dic.Value.Property("details").Add(json);
dic.Value.SelectToken("details").Add(json);
Solved.
dic.Value["details"].Last.AddAfterSelf(JObject.Parse(json));

Categories