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.
Related
I got a json as input. I don't know exact structure of that file. I need only add object to "KnownCollection" which may be in file or not. So if there is a collection add item into it, if there is not create a collection with an item. Question is how to do that with System.Text.Json, we used it and I don't want to add dependency on Newtonsoft
{
"UnknownProperty": 1,
"KnownCollection": [{
"ItemProperty1": "1",
"ItemProperty2": 2
}],
// More unknown properties
}
var item = new {ItemProperty1 = "2", ItemProperty2 = 2};
var fileContent = File.ReadAllBytes(filePath);
using var jsonDocument = JsonDocument.Parse(fileContent);
var knownCollection = jsonDocument.RootElement.GetProperty("KnownCollection");
//How to add item to knownCollection?
You could add the item to array like below:
[HttpGet]
public string Index()
{
var fileContent = System.IO.File.ReadAllBytes("filePath");
using (MemoryStream memoryStream1 = new MemoryStream())
{
using (Utf8JsonWriter utf8JsonWriter1 = new Utf8JsonWriter(memoryStream1))
{
using (JsonDocument jsonDocument = JsonDocument.Parse(fileContent))
{
utf8JsonWriter1.WriteStartObject();
foreach (var element in jsonDocument.RootElement.EnumerateObject())
{
if (element.Name == "KnownCollection")
{
utf8JsonWriter1.WritePropertyName(element.Name);
utf8JsonWriter1.WriteStartArray();
// Staring new object
utf8JsonWriter1.WriteStartObject();
utf8JsonWriter1.WriteString("ItemProperty1", "2");
utf8JsonWriter1.WriteNumber("ItemProperty2", 2);
utf8JsonWriter1.WriteEndObject();
// Copying existing values from "KnownCollection" array
foreach (var testDataElement in element.Value.EnumerateArray())
{
testDataElement.WriteTo(utf8JsonWriter1);
}
utf8JsonWriter1.WriteEndArray();
}
else
{
element.WriteTo(utf8JsonWriter1);
}
}
utf8JsonWriter1.WriteEndObject();
}
}
var resultJson = Encoding.UTF8.GetString(memoryStream1.ToArray());
return resultJson;
}
}
Result:
using (StreamReader r = new StreamReader(filePath))
{
string json = r.ReadToEnd();
JObject data = JObject.Parse(json);
foreach (var x in data)
{
if (x.Key.Contains(product))
{
Console.WriteLine(x.Key.Contains(product));
// for (int m = 0; m <= x.Value.ToString().Length; m++)
}
}
Console.WriteLine(tempList.Count);
Console.WriteLine("");
}
}
else
{
Console.WriteLine("ERROR: Data not returned by Database...");
return View();
}
}
else
{
Console.WriteLine("ERROR: No Value recieved by client...");
return View();
}
return View();
}
// -------------------------------------------------------------------------------------
// in the above snippet, I want to iterate on x.Value, like x.Value[0], then x.Value[1] and so on.
// The format of my json file is like this...
{
"BOOK": [ "FORMAT", "PAGE", "DIMENSION", "WEIGHT", "PUBLICATIONDATE", "LANGUAGE", "GENRE", "AUTHOR" ],
"COMPUTER": [ "BRAND", "TYPE", "COLOUR", "STORAGE", "CPU", "RAM", "SCREENSIZE", "CPMPUTERTYPE", "DISPLAYTYPE", "PROCESSORCORENUMBER", "SSDSTORAGE", "PORT", "BLUETOOTH", "OPERATINGSYSTEM" ],
"GAME": [ "FORMAT", "GENRE", "RATING", "DEVELOPER", "PUBLISHER" ],
"MOBILE": [ "BRAND", "COLOUR", "STORAGE", "SCREENSIZE", "NETWORK", "PHONEOPERATINGSYSTEM", "SCREENSIZEINCHES", "INTERNALSTORAGE", "BATTERYCAPACITYMAH", "CPU", "RAM", "REARCAMERAMP", "FRONTCAMERAMP", "FLASH", "HEADPHONEJACK", "BLUETOOTH", "RELEASEYEAR" ],
"MOVIE": [ "GENRE", "REGIONCODING", "RATING", "RELEASEYEAR", "FORMAT" ]
....
}
Its bit unclear what you actually want but let me try to help you.
Lets understand your JSON schema first. It has productCategory ("Book","Computer","Game" etc.) and each productCategory has array of properties (For "Book" -> [ "FORMAT", "PAGE", "DIMENSION",...]
So now if you want to iterate through your productCategory and count the length of it, you can do the following:
using (StreamReader r = new StreamReader(filePath))
{
string json = r.ReadToEnd();
JObject data = JObject.Parse(json);
foreach (var productCategory in data)
{
// counts the number of properties like for eg. For "Book" it has 8 properties like "Format","Page" etc.
var count = productCategory.Value.Children().ToList().Count;
Console.WriteLine($"{productCategory.Key} Count: {count}");
}
}
Output:
And if you also want to iterate through properties of each productCategory, you can do the following:
using (StreamReader r = new StreamReader(filePath))
{
string json = r.ReadToEnd();
JObject data = JObject.Parse(json);
foreach (var productCategory in data)
{
// counts the number of properties like for eg. For "Book" it has 8 properties like "Format","Page" etc.
var count = productCategory.Value.Children().ToList().Count;
Console.WriteLine($"{productCategory.Key} Count: {count}");
foreach (var properties in productCategory.Value)
{
//Here you will have properties like "Format","Page" etc..
Console.WriteLine(properties);
}
Console.WriteLine("");
}
}
Output:
Thanks a lot for trying to help me out.
Really appreciate it.
I tried the idea that OhmnioX gave and played around with the code, finally created the following snippet.
using (StreamReader r = new StreamReader(filePath))
{
string json = r.ReadToEnd();
JObject data = JObject.Parse(json);
foreach (var x in data)
{
if (x.Key.ToString().Contains(product))
{
var cnt = x.Value.Children().ToList().Count;
for (int m=0; m<=cnt-1; m++)
{
tempList.Add(x.Value[m].ToString().ToUpper());
}
}
}
}
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
I am trying to parse a json and populate these values into an object with DataContractJsonSerializer. Having no luck with this yet.
The json is -
{
"0": [
547,
541,
507,
548,
519,
0
],
"1": [
573,
504
]
}
I have tried the following code:
try
{
string json = #"""0"":[547,541,507,548,519,0],""1"":[573,504]";
using (var memStream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
{
var seraializer = new DataContractSerializer(typeof(MyClass));
var jsonParsed = seraializer.ReadObject(memStream);
}
}
catch(Exception ex)
{
}
Always getting an exception that the data is invalid at the root. But online json validators say this is a valid json.
MyClass -
[DataContract]
public class MyClass
{
[DataMember]
public Dictionary<string, List<int>> values { get; set; }
}
Thanks Patrick for providing me a working solution with Newtonsoft. But just to learn , I want to see what am I doing wrong with DataContractJsonSerializer. The code below gives me no exception, but I am not getting any values after the parsing is complete.
string json = #"{""0"":[547,541,507,548,519,0],""1"":[573,504]}";
using (var memStream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
{
var seraializer = new DataContractJsonSerializer(typeof(Dictionary<string, List<int>>));
var jsonParsed = seraializer.ReadObject(memStream);
}
You should use Dictionary<string, List<int>> as the type to deserialize to. You also need to use the right serializer (DataContractSerializer is for XML, DataContractJsonSerializer for JSON):
var seraializer = new DataContractJsonSerializer(typeof(Dictionary<string, List<int>>), new DataContractJsonSerializerSettings() { UseSimpleDictionaryFormat = true });
var jsonParsed = seraializer.ReadObject(memStream);
Or for JSON.NET:
var x = JsonConvert.DeserializeObject<Dictionary<string, List<int>>>(json);
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();
(...)