How do I loop over this JObject? - c#

I am able to read the json file and store it in a JObject variable. I need to check for null values and ignore any segment that has null values. I was thinking of looping through the JObject but I don't know how i can access every segment/ key in the json below.
I think we can loop like this based on another question i saw on here:
foreach (var x in example) //example is the JObject in which json file is stored
{
string name = x.Key;
JToken value = x.Value;
}
But my json doesnt have keys. How do i go in every segment and check if name, description values are not null?
My json is :
{
"lorem ipsum Segment Groups":[
{
"name":"lorem ipsum",
"description":"lorem ipsum",
"segments":[
"Not Enrolled",
"Started Enrollment – Zipcode Lookup",
"Started Enrollment – Passed Flow Step 1",
"Started Enrollment – Passed Flow Step 2"
]
},
{
"name":"lorem ipsum",
"description":"Status Description",
"segments":[
"Moving in next 30 days",
"Moving in next 90 days",
"Not Moving"
]
},
{
"name":"lorem ipsum",
"description":"Interest description",
"segments":[
"Interested - Lots of Time Reading Many Pages",
"Interested - Lots of Time Comparing Products/Prices"
]
}
]
}
Thanks

Here is an example of how to loop through your JSON:
JObject obj = JObject.Parse(json);
JArray segmentGroups = (JArray)obj.Properties().FirstOrDefault()?.Value;
if (segmentGroups != null)
{
foreach (JObject group in segmentGroups.Children<JObject>())
{
string name = (string)group["name"];
string desc = (string)group["description"];
string[] segments = group["segments"]?.ToObject<string[]>();
Console.WriteLine("name: " + (name ?? "(null)"));
Console.WriteLine("description: " + (desc ?? "(null)"));
Console.WriteLine("segments: " + (segments != null ? "\n " + string.Join("\n ", segments) : "(null)"));
Console.WriteLine();
}
}
Fiddle: https://dotnetfiddle.net/kOJzaZ

By knowing the JSON structure, you can use various types with name formatted as JXxx to read the values you want. However here there is one convenient way of selecting the tokens you want by using a json path. That way you can conveniently target the desired set of tokens and continue processing. I'm not so sure about the performance hit with that approach but you may take its trade-off (and if performance does matter, just try benchmarking it first).
The code can be simple like this:
//suppose your example is the loaded JObject
foreach (var group in example.SelectTokens("['lorem ipsum Segment Groups'][*]"))
{
var name = group["name"].Value<string>();
var desc = group["description"].Value<string>();
//check if they are null here ...
}
Note the way we escape keys or paths containing spaces by wrapping it inside ['']. If your key does not need to be escaped, you can use it directly in the path.

Related

Write json object values without { ": , using c#

{
"FirstName" :"Kaustubh",
"LastName" :" Sawant ",
"StartTime" :"01:00:00"
}
I want to get printed
First Name: Kaustubh
Last Name: Sawant
Start time : 01:00:00
This is the demo code written the actual object retrieves more values.
Actual code :
String JsonValue=JsonConvert.SerializsObject(object);
also used Formatting.Indented and tried
Regex.Replace(JsonValue,#"\{},"","").Trim();
and then wrote into file using StreamWriter.
I think you are attacking this from the wrong angle, if this is truly json, you are best to deserialize it using something like json.net, and then building the string up out of the properties.
However, because you insist on doing it via replacement, you can make use of regex
var result = Regex.Replace(input, #"[,{}\"")]", "").Trim();
Console.WriteLine(result);
Output
FirstName :Kaustubh
LastName : Sawant
StartTime :01:00:00
Full Demo Here
Considering json is a string variable containing your input:
var json = #"
{
""FirstName"" :""Kaustubh"",
""LastName"" :"" Sawant "",
""StartTime"" :""01:00:00""
}";
Simple solution relying on standard library:
Console.WriteLine(json.Replace("{", "").Replace("}", "").Replace("\"","").Replace(",", "").Trim());
A solution using Newtonsoft.Json framework for deserializing json string:
var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
foreach (var entry in dict)
{
Console.WriteLine($"{entry.Key}: {entry.Value}");
}

Convert string of tab seperated data into list of objects in C#

I am facing hard time converting below string of input in C#. As you can see, the string of input are each in a new line seperated by \r\n. And each input data in one line is seperated by \t
I need to delete the lines which start with '!'
!710889\tF\t3400\r\n
BY\tF\t5000\r\n
G1\tC\t600\r\n
So Valid input file would be
BY\tF\t5000\r\n
G1\tC\t600\r\n
I need to convert this into following
Object {Info: Array[3]}
> Info: Array[3]
>[0]: Object
id: 'BY'
type: 'F'
value: 3400
>[1]: Object
id: 'G1'
type: 'C'
value: 600
Following thing was tried but no success
string[] values = str.Split("\t".ToCharArray());
// ... do something with "values" ...
xxx.aaa = values[0];
xxx.bbb = values[1];
xxx.ccc = values[2];
It didnt list all the elements as i wanted. Can someone please shed some light here
Take baby steps, and things get easier:
Get an enumeration of lines from the input string:
var lines = input.Split(new[] { Environment.NewLine },
StringSplitOptions.RemoveEmptyEntries);
Filter out those you don't need:
var validLines = lines.Where(s => !s.StartsWith('!'));
Split each valid line into your object fields and build a ValueTuple with the data:
foreach (var line in validLines)
{
var fields = line.Split('\t');
yield return ( fields[0],
fields[1],
int.Parse(fields[2]) };
}
Note I've used C#7 native tuple support. If you are not using C#7, you'll have to change the code slightly. Anyway, putting everything together:
static IEnumerable<(string Id, string Type, int Value)>
ParseData(string input)
{
var lines = input.Split(new[] { Environment.NewLine },
StringSplitOptions.RemoveEmptyEntries);
var validLines = lines.Where(s => !s.StartsWith('!'));
foreach (var line in validLines)
{
var fields = line.Split('\t');
yield return ( fields[0],
fields[1],
int.Parse(fields[2]));
}
}
I've obviously omitted any error checking or data validation. I'll leave that to you, but there are a lot of things that can go wrong in the code above: field count is not 3, parsing field[2] fails, etc.

Is there an easy way to parse a structured text file in C#?

I'm trying to parse a text file, but I feel like there must be a better way to do it.
The text file is made up of items, which can contain both key value pairs as well as other items. I believe the file will only ever go as deep as a grandchild item (e.g. an item within an item, within an item).
Currently I'm iterating through the file line by line, and keeping track of the depth at which I am. Then once I reach a termination character ('}') and I'm at level 0, I know I've captured a whole parent item.
Since I don't think I've explained it well, my file structure will look similar to this.
parent_item {
key: value
key: value
child_item {
key: value
key: value
}
child_item {
key: value
key: value
key: value
grandchild_item {
key: value
key: value
}
}
key: value
key: value
}
parent_item {
key: value
key: value
child_item {
key: value
key: value
}
}
Each item can have 0 to many child items, though I don't think it will ever go deeper than 3 levels (parent -> child -> grandchild).
Is there an easier way to parse this, or am I working in the right direction?
Your file looks almost like JSON, except there are no colons between property names of a complex nested object. However, it is different enough that you won't be able to use a JSON parser like JSON.NET.
I recommend parsing it manually like you are doing-- but use a stack and state machine. Your state machine should push to the stack every time you encounter the open curly { and pop from the stack when you get the close curly }.
Being so similar to JSON, if the formatting is constant (open curly ´{´ and end curly } as the last character in the line) you could translate that text into JSON with minor changes. Warning, not tested, something like this:
StringBuilder jsonEncoded = new StringBuilder();
string[] lines = content.Split("\n");
foreach(string line in lines)
{
if(line.EndsWith("{") || line.EndsWith("}")
jsonEncoded.AppendLine(line);
else
jsonEncoded.AppendLine(line + ",");
}
After that, a regular JSON Deseralization would work.
If you can trust your source for not messing with this schema you can write a workaround. I have some ideas for you:
JSON
It looks like json. Maybe you can normalize it, then parse it with JSON.NET.
I just write a ugly but working solution. Try it here:
using System;
using System.Text.RegularExpressions;
public class Program
{
public static string Quoterize(string s)
{
return Regex.Replace(s, #"\w+", match => "\"" + match + "\"");
}
public static string RewriteThisPlease(string s)
{
return s
.Replace("\n", "," + Environment.NewLine)
.Replace(" ", "")
.Replace(Environment.NewLine, "")
.Replace("{,", "{")
.Replace(",}", "}");
}
public static void Main()
{
var k = #""; // your file goes here
Console.WriteLine("{"+MoveToRegexPlease(Quoterize((k).Replace("{", ": {")))+"}");
}
}
YAML
It looks like json. It looks even more like yaml. A yaml validator will accept your file after two simples replace:
// where k is your file as string
Console.WriteLine(k.Replace("{\n", ":\n").Replace("}",""));
Demo
Homemade
It looks like json. You will find a lot of JSON parser out there, maybe you can fork one and adapt it to works with your case.
Homework
It looks like json. You will find a lot of JSON parser tutorial out there. Writing a small parser is always a good exercise.
Good luck !
Here is a brief example (though not carefully tested yet) of using RegEx with Balancing Group Definitions
This example uses the code from the link. I just replaces the parentheses to not change the code and use it as it is:
static void Main(string[] args)
{
// here I read your posted file
string input = System.IO.File.ReadAllText("test.txt");
input = input.Replace('{', '<');
input = input.Replace('}', '>');
string pattern = "^[^<>]*" +
"(" +
"((?'Open'<)[^<>]*)+" +
"((?'Close-Open'>)[^<>]*)+" +
")*" +
"(?(Open)(?!))$";
//string input = "<abc><mno<xyz>>";
Match m = Regex.Match(input, pattern);
if (m.Success == true)
{
Console.WriteLine("Input: \"{0}\" \nMatch: \"{1}\"", input, m);
int grpCtr = 0;
foreach (Group grp in m.Groups)
{
Console.WriteLine(" Group {0}: {1}", grpCtr, grp.Value);
grpCtr++;
int capCtr = 0;
foreach (Capture cap in grp.Captures)
{
Console.WriteLine(" Capture {0}: {1}", capCtr, cap.Value);
capCtr++;
}
}
}
else
{
Console.WriteLine("Match failed.");
}
Console.ReadKey();
}
Copy paste this into a new console project, let it run and take a look at the output. It is confusing in the beginning, but it might give you a starter to adjust it to your needs.
Use Serialisation.
In C# you can easily use JSON or XML serialisation.
JSON:
https://msdn.microsoft.com/en-us/library/bb412179(v=vs.110).aspx
A better way would be XML because it is more flexible and has a better support in C#:
https://msdn.microsoft.com/en-us/library/58a18dwa(v=vs.110).aspx

Newtonsoft Json.Net correct parsing of string arrays inside a JSON object

I have the following problem, I want to parse a Json object I get passed by a url query string
e.g.
...&json={tags=[tag1,tag2]}
I have used
JsonConvert.DeserializeObject<Dictionary<string, object>>(json)
But when calling the Deserialize method I get an error
Newtonsoft.Json.JsonReaderException : Unexpected character encountered while parsing value: d. Line 1, position 8.
If I pass in the string
"{tags:[\"tag1\",\"tag2\"]}
It works fine, I don't want my users to have to add the "" quotes
Is there a way to work around this problem?
pseudocode For a solution could be...
Grab the json query string element.
Split on first equals "=".
Grab all text between "{tags=[" and "]}"
Take that text split on ","
trim any whitespace off of the items.
Join them back together but put quotes around them and coma delimited them.
put that value back inbetween "{tags=[" and "]}" ie "{tags=[" + newValue+ "]}"
Here is some sample C# code...
[Test]
public void TestHack()
{
string almost = "{tags=[tag1,tag2]}";
string json = this.HackToJson(almost);
Trace.WriteLine(json);
}
public string HackToJson(string almostJson)
{
if( almostJson.StartsWith("{tags=[") && almostJson.EndsWith("]}"))
{
int tagsLen = "{tags=[".Length;
string tags = almostJson.Substring(tagsLen, almostJson.Length - (tagsLen + 2));
var items = tags.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries);
var itemsCleaned = (from c in items select "\"" + c.Trim() + "\"");
var jsonpart = string.Join(",", itemsCleaned);
var json = string.Format("{{tags=[{0}]}}", jsonpart);
return json;
}
throw new NotImplementedException("not sure what to do here... ");
}

Parsing JSON API in C#

so I'm fairly new to programming but am looking to go much deeper with it. I recently started to get involved in a project to create a WinForm program for a website that uses an API system in JSON.
I've never used an API before so I'm not quite sure how it works but after looking at it for a few minutes I seem to have the gist of it. What I don't get is how exactly parsing JSON in C# works.
I found
this link after a little google searching. And I got it working (somewhat) with this code.
static void Main(string[] args)
{
WebClient c = new WebClient();
var vLogin = c.DownloadString("https://www.openraid.us/index.php/api/login/username/password");
//Returns string
//{"status":1,"error":null,"token":"250-1336515541-c48d354d96e06d488d1a2530071ef07c9532da26"}
//Token = random, no decisive length*/
JObject o = JObject.Parse(vLogin);
Console.WriteLine("Login Status: " + o["status"]);
String sToken = "" + o["token"];
Console.WriteLine(sToken);
Console.WriteLine("");
//Breaks after this
var myRaids = c.DownloadString("https://www.openraid.us/index.php/api/myraids/"+sToken);
JObject r = JObject.Parse(myRaids); //error occurs here
String sEventId = "" + r["event_id"];
Console.WriteLine("Event ID: " + sEventId);
Console.ReadLine();
}
So to me it looks like I have parsing 1 page done and handled, but when I move onto the second I get this error.
Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path '', line 1, position 1.
So I guess my question is, how do I parse more than 1 page or call of JSON and what would be the easiest way to break up each section of the JSON object (Such as status, error, and token, into C# strings?
Did you try to JArray instead? Depending on what kind of object you are trying to return
WebClient client = new WebClient();
var data = client.DownloadString("");
var jArray = JArray.Parse(data);
JSON requires brackets for arrays and commas between multiple objects.
This is per the JSON standard. I also recommend using JSON.net via NuGet instead of the native JSON parser unless it is overkill and you cannot have the extra bloat.
For example, your parsing a file with two seperate JSON objects - the following does not work per the JSON standard (lacks a comma between the 2 objects and the two objects are not encapsulated by brackets):
{"status":1,"error":null}
{"status":2,"error":null}
The following 3 JSON objects parsed from a file does work (has brackets for multiple objects and commas between objects):
[{"glossary": {"title": "fun glossary","SeeAlso": ["GML", "XML"]},
{"glossary": {"title": "grey glossary","SeeAlso": ["GML", "XML"]},
{"glossary": {"title": "blue glossary","SeeAlso": ["GML", "XML"]}]
You can cut every JSON object(Array) into more object using for loops
the C# API is System.Json
var jsonArray = JsonArray.Parse(st);//st is the string which contain the JSON objects
foreach (var item in jsonArray) {
JsonObject ob = new JsonObject(item);
foreach (var t in ob.Values) {
JsonObject oo = new JsonObject(t);
foreach (var x in oo) {
textBox1.AppendText(x.Key + “ : ” + x.Value + “\n”);
}
}
}

Categories

Resources