How to parse two different JSON formats - c#

I need to parse 2 different types of JSONs as shown below:
JSON 1:
{
"projects": [
{
"sno": "1",
"project_name": "Abs",
"project_Status": "Live"
},
{
"sno": "2",
"project_name": "Cgi",
"project_Status": "Live"
}
]
}
JSON 2:
[
{
"sno": "1",
"project_name": "Disc",
"project_Status": "Live"
},
{
"sno": "2",
"project_name": "Rol",
"project_Status": "Live"
}
]
I was parsing the JSON 2 as follows:
using (StreamReader streamReader = new StreamReader(Path.Combine(Path.GetTempPath(), "sample.json")))
using (JsonTextReader reader = new JsonTextReader(streamReader))
{
var serializer = new JsonSerializer();
while (reader.Read())
{
if (reader.TokenType == JsonToken.StartObject)
{
JObject jsonPayload = JObject.Load(reader);
jsonProfile = jsonPayload.ToString();
JObject json = JObject.Parse(jsonProfile);
}
}
}
Is it possible for me to modify this to check if the JSON is in type 1 or type 2 and then parse it to assign each project to a different JObject?

Unless your JSON is large (thousands of lines), I would dispense with the reader altogether. Instead, read the whole JSON file into a string using File.ReadAllText and parse it using JToken.Parse. From there it is easy to check whether you have an array (JSON 2) or an object containing an array (JSON 1) and then process accordingly:
string fileName = Path.Combine(Path.GetTempPath(), "sample.json");
string json = File.ReadAllText(fileName);
JToken token = JToken.Parse(json);
JArray array = (token.Type == JTokenType.Array) ? (JArray)token : (JArray)token["projects"];
foreach (JObject project in array)
{
Console.WriteLine("number: " + (string)project["sno"]);
Console.WriteLine("name: " + (string)project["project_name"]);
Console.WriteLine("status: " + (string)project["project_Status"]);
Console.WriteLine();
}
Fiddle: https://dotnetfiddle.net/lA87Xo

Related

How to add property in existing json

I receive a JSON file like this:
{
"Name": "testeName",
"type": "unique",
"TestData": [{
"price": 2.3
}]
}
I want to add a new property ("type":"unique") to each object in TestData to be like this in the end:
{
"Name": "testeName",
"type": "unique",
"TestData": [{
"price": 2.3,
"type": "unique"
}]
}
Is there any way to do it with less code? I try this but there's a lot of code, I believe there must be a simpler way:
using (MemoryStream memoryStream1 = new MemoryStream())
{
using (Utf8JsonWriter utf8JsonWriter1 = new Utf8JsonWriter(memoryStream1))
{
using (JsonDocument jsonDocument = JsonDocument.ParseValue(ref reader))
{
utf8JsonWriter1.WriteStartObject();
foreach (var element in jsonDocument.RootElement.EnumerateObject())
{
if (element.Name == "price")
{
// Copying existing values from "TestData" object
foreach (var testDataElement in element.Value.EnumerateArray())
{
utf8JsonWriter1.WritePropertyName(element.Name);
// Staring new object
utf8JsonWriter1.WriteStartObject();
// Adding "Name" property
utf8JsonWriter1.WritePropertyName("type");
utf8JsonWriter1.WriteStringValue("unique");
//System.InvalidOperationException : 'Cannot write the start of an object or array without a property name. Current token type is 'String'.'
testDataElement.WriteTo(utf8JsonWriter1);
}
utf8JsonWriter1.WriteEndObject();
}
else
{
element.WriteTo(utf8JsonWriter1);
}
}
utf8JsonWriter1.WriteEndObject();
}
}
var resultJson = Encoding.UTF8.GetString(memoryStream1.ToArray());
}
you can try this code
using Newtonsoft.Json;
var jsonObject = JObject.Parse(json);
var testDataObj = (JObject) ((JArray)jsonObject["TestData"])[0];
testDataObj.Add("type", "unique");
json=jsonObject.ToString();
result
{
"Name": "testeName",
"type": "unique",
"TestData": [
{
"price": 2.3,
"type": "unique"
}
]
}
Can you use the Newtonsoft JSON Nuget package?
You can read JSON from a file, then use the JObject.Add method to add a property and value to the JSON object:
using (StreamReader file = File.OpenText("[insert your file path here]"))
using (JsonTextReader jtReader = new JsonTextReader(file))
{
JObject jObj = (JObject)JToken.ReadFrom(reader);
jObj.Add("type", "unique");
}
In .NET 6 and later you may use the new JsonNode editable JSON Document Object Model to load, modify and re-serialize your JSON:
// Load the file
JsonObject root;
using (var stream = File.OpenRead(inputFileName))
{
root = (JsonNode.Parse(GetJson()) ?? new JsonObject()).AsObject();
}
// Add "type" to "TestData[*]"
if (root["TestData"] is JsonArray array)
{
foreach (var obj in array.OfType<JsonObject>())
{
obj["type"] = "unique";
}
}
//Examine the resulting JSON string
var resultJson = root.ToString();
//Or write back the file directly, without using an intermediate JSON string
using (var stream = File.Create(outputFileName))
using (var writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = true }))
{
root.WriteTo(writer);
}
Demo fiddle here.

Serialize flat Dictionary into multi-sub-object JSON

In C# I have a flat Dictionary<string, string> where keys are in form of obj1/obj2/obj3 and values are direct string. Now I want to serialize that into subobjects, so example values:
var dict = new Dictionary<string, string> { {"foo/bar/baz1", "123" }, {"foo/baz", "456" }, { "foo/abc", "def" } };
should result with:
{
"foo": {
"bar": {
"baz1": "123"
},
"baz": "456",
"abc": "def"
}
}
Optionally I want to remove quotes around "123" and "456" in output if they can be interpreted as numbers or booleans.
I am using Newtonsoft.JSON
You can parse a source dictionary into JObject using JObject.FromObject method. Then go through all of properties, split them using string.Split and parse recursively to a new JObject, representing a properties tree. Finally add this object to the destination one using JObject.Add, or update it if the given key is already exist
var dict = new Dictionary<string, string> { { "foo/bar/baz1", "123" }, { "foo/baz", "456" }, { "foo/abc", "def" } };
var source = JObject.FromObject(dict);
var dest = new JObject();
foreach (var property in source.Properties())
{
//split the name into parts
var items = property.Name.Split(new[] { "/" }, StringSplitOptions.RemoveEmptyEntries);
var item = items.FirstOrDefault();
if (string.IsNullOrEmpty(item))
continue;
//get JObject representing a properties tree
var result = WriteItems(items.Skip(1).ToList(), property.Value);
//check that destination already contains top property name (e.g. 'foo')
if (dest.ContainsKey(item))
{
(dest[item] as JObject)?.Add(result.First);
}
else
{
dest.Add(item, result);
}
}
Console.WriteLine(dest.ToString());
//local function to recursively go through all properties and create a result JObject
JObject WriteItems(IList<string> items, JToken value)
{
var item = items.FirstOrDefault();
items.RemoveAt(0);
if (!items.Any()) //no more items in keys, add the value
return new JObject(new JProperty(item, value));
return new JObject(new JProperty(item, WriteItems(items, value)));
}
It produces the following output
{
"foo": {
"bar": {
"baz1": "123"
},
"baz": "456",
"abc": "def"
}
}
Also, the code above allows you to handle a properties tree with any depth. I don't think that there is a built-in way to serialize the structure like foo/bar/baz1 into sub-objects in Json.NET

C# Deserialize string of multiple arrays with json-string in it explicit to List<string>

i have a json-string, or bit more something like a "string of arrays":
"[
{
"type":"radio-group",
"label":"Radio-Button-Gruppe",
"name":"radio-group-1556028993486",
"className":"iCheck",
"values":[
{
"label":"aaaaaaa",
"value":"aaaaaaa"
},
{
"label":"bbbbbbbbb",
"value":"bbbbbbbbb"
},
{
"label":"cccccccccccc",
"value":"cccccccccccc"
}
]
}
],
[
...
],
[
{
"type":"header",
"label":"Überschrift"
}
]"
Now I want to have a List<string> of each array in this string. Something like:
List<string> x[0] = "{
"type":"radio-group",
"label":"Radio-Button-Gruppe",
"name":"radio-group-1556028993486",
"className":"iCheck",
"values":[
{
"label":"aaaaaaa",
"value":"aaaaaaa"
},
{
"label":"bbbbbbbbb",
"value":"bbbbbbbbb"
},
{
"label":"cccccccccccc",
"value":"cccccccccccc"
}
]
}"
What's the best way to do that?
I already tried out JsonConvert.DeserializeObject<IEnumerable<string>>() but my problem is that he wants to deserialize my jsons to an object. But I want to keep them as a string und put them to my list.
Why I need a list of string for each array?
Because I use the json-strings inside the arrays to render a form. each array show you a page of the form, and the json is the data for rendering this form.
to render this form i have to go through a loop through all of this arrays and render the json in it for every page.
You can use JsonConvert.DeserializeObject<IEnumerable<JToken>>(json) where json is each of your top level arrays. Then you can iterate through the results and use .ToString() on each JToken object.
As others have pointed out, you don't have valid JSON, so I didn't try to give a solution to parse out the top level arrays.
var json = #"[
{
""type"":""radio-group"",
""label"":""Radio-Button-Gruppe"",
""name"":""radio-group-1556028993486"",
""className"":""iCheck"",
""values"":[
{
""label"":""aaaaaaa"",
""value"":""aaaaaaa""
},
{
""label"":""bbbbbbbbb"",
""value"":""bbbbbbbbb""
},
{
""label"":""cccccccccccc"",
""value"":""cccccccccccc""
}
]
}
]";
var arrays = new[] { json };
var objectsAsStrings = new List<string>();
foreach (var array in arrays)
{
var tokens = JsonConvert.DeserializeObject<IEnumerable<JToken>>(array);
foreach (var token in tokens)
{
objectsAsStrings.Add(token.ToString());
}
}
var json = "yourjson";
var jsonnew = "[" + json+ "]";
var list = JsonConvert.DeserializeObject<dynamic>(jsonnew);
var result = new List<string>();
foreach (var item in list)
{
var str = JsonConvert.SerializeObject(item);
result.Add(str);
}
You can use this , too.

How to Modify JSON object inside JSON array in c#?

This is my Json Array
[
{
"gregdate": "06-03-2019",
"maldate": "22-07-1194",
"gregmonth": "March",
"selected_status": "1"
},
{
"gregdate": "04-05-2019",
"maldate": "21-09-1194",
"gregmonth": "May",
"selected_status": "1"
},
{
"gregdate": "03-06-2019",
"maldate": "20-10-1194",
"gregmonth": "June",
"selected_status": "1"
}
]
In this JSON Array, I want to change 2nd JSON Object "selected_status" value "1" to "0" without changing the position of the JSON Object.
You need to first convert you object array to JArray and then change its second object property from 1 to 0 like
string json = "You json here"; //Load your json
JArray jArray = JArray.Parse(json); //Parse it to JArray
var jObjects = jArray.ToObject<List<JObject>>(); //Get list of objects inside array
foreach (var obj in jObjects) //Loop through on a list
{
if (jObjects.IndexOf(obj) == 1) //Get 2nd object from array
{
foreach (var prop in obj.Properties()) //List 2nd objects properties
{
if (prop.Name == "selected_status") //Get desired property
obj["selected_status"] = 0; //Change its value
}
}
}
JArray outputArray = JArray.FromObject(jObjects); //Output array
Alternative:
As suggested by Brian Rogers you can directly query your JArray to replace its specific property value like,
string json = "You json here"; //Load your json
JArray jArray = JArray.Parse(json); //Parse it to JArray
jArray[1]["selected_status"] = "0"; //Querying your array to get property of 2nd object
string outputJson = jArray.ToString(); //Output json
Output: (from debugger)
This question helped me figure a couple things out - so here is what I came up with. I'm guessing that the json is a sample and what is desired is changing the status for a specific date, rather than just the second element. At least that's what I've been looking for. This is more dynamic and you don't have to worry about the position of the element.
string newJson = "";
if (SwitchStatus(jsonString, "04-05-2019", "0", out newJson))
{
Console.Write(newJson);
}
else
{
Console.WriteLine("Date Not Found");
}
Console.ReadLine();
static bool SwitchStatus(string jsonString, string searchBy, string switchTo, out string output)
{
dynamic jsonObj = JsonConvert.DeserializeObject(jsonString);
JToken status = jsonObj.SelectToken($"$..[?(#.gregdate == '{searchBy}')].selected_status");
if (status != null)
{
status.Replace(switchTo);
output = JsonConvert.SerializeObject(jsonObj, Newtonsoft.Json.Formatting.Indented);
}
else
{
output = jsonString;
}
return status != null;
}

Parsing a JSON array using Json.Net

I'm working with Json.Net to parse an array. What I'm trying to do is to pull the name/value pairs out of the array and assign them to specific variables while parsing the JObject.
Here's what I've got in the array:
[
{
"General": "At this time we do not have any frequent support requests."
},
{
"Support": "For support inquires, please see our support page."
}
]
And here's what I've got in the C#:
WebRequest objRequest = HttpWebRequest.Create(dest);
WebResponse objResponse = objRequest.GetResponse();
using (StreamReader reader = new StreamReader(objResponse.GetResponseStream()))
{
string json = reader.ReadToEnd();
JArray a = JArray.Parse(json);
//Here's where I'm stumped
}
I'm fairly new to JSON and Json.Net, so it might be a basic solution for someone else. I basically just need to assign the name/value pairs in a foreach loop so that I can output the data on the front-end. Has anyone done this before?
You can get at the data values like this:
string json = #"
[
{ ""General"" : ""At this time we do not have any frequent support requests."" },
{ ""Support"" : ""For support inquires, please see our support page."" }
]";
JArray a = JArray.Parse(json);
foreach (JObject o in a.Children<JObject>())
{
foreach (JProperty p in o.Properties())
{
string name = p.Name;
string value = (string)p.Value;
Console.WriteLine(name + " -- " + value);
}
}
Fiddle: https://dotnetfiddle.net/uox4Vt
Use Manatee.Json
https://github.com/gregsdennis/Manatee.Json/wiki/Usage
And you can convert the entire object to a string, filename.json is expected to be located in documents folder.
var text = File.ReadAllText("filename.json");
var json = JsonValue.Parse(text);
while (JsonValue.Null != null)
{
Console.WriteLine(json.ToString());
}
Console.ReadLine();
I know this is about Json.NET but times are a-changing so if anybody stumbles here while using .NET Core/5+ System.Text.Json please don't despair because
Try the new System.Text.Json APIs from .NET Blog show an example of this.
[
{
"date": "2013-01-07T00:00:00Z",
"temp": 23,
},
{
"date": "2013-01-08T00:00:00Z",
"temp": 28,
},
{
"date": "2013-01-14T00:00:00Z",
"temp": 8,
},
]
...
using (JsonDocument document = JsonDocument.Parse(json, options))
{
int sumOfAllTemperatures = 0;
int count = 0;
foreach (JsonElement element in document.RootElement.EnumerateArray())
{
DateTimeOffset date = element.GetProperty("date").GetDateTimeOffset();
(...)

Categories

Resources