I am insert data into .json file. My insertion works fine, but I have a problem - when I insert new data, the previous data in the file is deleted.
How can I manage that?
Also I would need it to be in the format of because I need to query it:
[
{
"Rollnumber": 3,
"StudentName": "Tapas"
},
{
"Rollnumber": 4,
"StudentName": "Papas"
}
]
When I pass the data as the list.ToArray()(that would be the _data in the code example) I get the [] brackets, but only on the first data with rollnumber = 3.
This is my code so far:
private void AddStudent()
{
Student objStudent = new Student();
objStudent.Rollnumber = 3;
objStudent.StudentName = "Tapas";
/* List<Student> _data = new List<Student>();
_data.Add(new Student()
{
Rollnumber = 4,
StudentName = "Papas"
});
*/
string jsonData = JsonConvert.SerializeObject(objStudent, Formatting.Indented);
System.IO.File.WriteAllText(jsonFileS, jsonData);
}
I have tried with the StreamWritter also, but I could not do it.
Retrieve the source file that containing JSON.
Read text content (JSON data) from source file.
Deserialize JSON data to List of student object.
Add new student student list.
Serialize the student list, you will get JSON data string as return from that method.
Save JSON string to the source file.
Here is example code:
var file = await ApplicationData.Current.LocalFolder.GetFileAsync(fileName);
var jsonString = await FileIO.ReadTextAsync(file);
var studentList = JsonConvert.DeserializeObject<List<Student>>(jsonString);
var newStudent = new Student();
newStudent.Rollnumber = 2;
newStudent.StudentName = "Abcd";
studentList.Add(newStudent);
var updatedJsonString = JsonConvert.SerializeObject(studentList);
await FileIO.WriteTextAsync(file, updatedJsonString);
I think in your situation, you can do a little trick like :
1, Read data from file
StreamReader sw = new StreamReader(fileName);
string res = sw.ReadToEnd();
2, Remove the "]" of the "res"(res variable) and add new Json string(remove the "[" and add ",") with your format.
So your string will look like two strings bellow adding together
[
{
"Rollnumber": 3,
"StudentName": "Tapas"
}
// Cut the last "]"
and
// cut the first "[" and add ","
,
{
"Rollnumber": 4,
"StudentName": "Papas"
}
]
So it will become what you want in the final :
[
{
"Rollnumber": 3,
"StudentName": "Tapas"
},
{
"Rollnumber": 4,
"StudentName": "Papas"
}
]
The answer is on this link : append to a json file
var jsonData = System.IO.File.ReadAllText(jsonFile);
// De-serialize to object or create new list
var employeeList = JsonConvert.DeserializeObject<List<Student>>(jsonData)
?? new List<Student>();
// Add any new employees
employeeList.Add(new Student()
{
Rollnumber = 1,
StudentName = "Paja1",
Subject = new Subject
{
Id = 1,
Name = "Sub1"
}
});
employeeList.Add(new Student()
{
Rollnumber = 1,
StudentName = "Pera1",
Subject = new Subject
{
Id = 1,
Name = "Sub1"
}
});
// Update json data string
jsonData = JsonConvert.SerializeObject(employeeList,Formatting.Indented);
System.IO.File.WriteAllText(jsonFile, jsonData);
As I mentioned in my comments to your question, you need to either load the entire file, deserialize it and then add items to it in memory. Once done, rewrite to the file by serializing it.
If you do not want to load the entire file into memory, then work with the file manually by manipulating the serialized string and then append to the file; else you will end up with bad JSON in file.
Here is the first method wherein you deserialize the entire file:
public static class Program
{
public static void Main()
{
var rolls = LoadRolls();
// Once the contents of the file are in memory you can also manipulate them
Roll firstRoll = rolls.SingleOrDefault(x => x.Rollnumber == 1);
if (firstRoll != null)
{
firstRoll.StudentName = "Jerry";
}
// Let's just add a few records.
rolls.AddRange(
new List<Roll>{
new Roll { Rollnumber = 1, StudentName = "Elaine" },
new Roll { Rollnumber = 2, StudentName = "George" }
});
string json = JsonConvert.SerializeObject(rolls, Newtonsoft.Json.Formatting.Indented);
File.WriteAllText("Rolls.txt", json);
Console.Read();
}
private static List<Roll> LoadRolls()
{
List<Roll> rolls = JsonConvert.DeserializeObject<List<Roll>>(File.ReadAllText("Rolls.txt"));
return rolls ?? new List<Roll>();
}
}
public class Roll
{
public int Rollnumber { get; set; }
public string StudentName { get; set; }
}
Related
I would like to insert data as array of json objects into a postgresql table column.
db table structure (create command for the table):
CREATE TABLE Recipes (
key SERIAL PRIMARY KEY,
name varchar(255) NOT NULL,
ingredients json[],
duration int);
A working sql query example (with any sql client):
INSERT INTO
recipes (name, duration, ingredients)
VALUES(
'title',
60,
array['{"name": "in1",
"amount": 125,
"unit": "g" }',
'{ "name": "in2",
"amount": 75,
"unit": "ml" }'
]::json[]);
In npgsql I try it as following:
//Create connection
var connString = $"Host={host};Port={port};Username={user};Password={password};Database={database}";
Npgsql.NpgsqlConnection.GlobalTypeMapper.UseJsonNet();
await using var conn = new NpgsqlConnection(connString);
await conn.OpenAsync();
//create query command
await using var cmd = new NpgsqlCommand("INSERT INTO recipes (name,duration,ingredients) VALUES (#p0,#p1,#p2)", conn)
{
Parameters =
{
new NpgsqlParameter("p0", recipe.Name),
new NpgsqlParameter("p1", recipe.Duration),
new NpgsqlParameter("p2", recipe.Ingredients)
}
};
//execute query
await cmd.ExecuteNonQueryAsync();
I have two classes from which I want generate the query params:
public class Recipe
{
public Recipe() { }
public string Name { get; set; }
public int Duration { get; set; }
//tried this --> did not help
//[Column(TypeName = "jsonb")]
public Ingredients[] Ingredients { get; set; }
}
public class Ingredients
{
public string Name { get; set; }
public float Amount { get; set; }
public string Unit { get; set; }
}
Since I was not able to do so, I tried to debug with hard coded stuff like this:
JObject jsonObject1 = new JObject();
jsonObject1.Add("name", "value1");
jsonObject1.Add("amount", 1);
jsonObject1.Add("unit", "ml");
JObject jsonObject2 = new JObject();
jsonObject2.Add("name", "value2");
jsonObject2.Add("amount", 2);
jsonObject2.Add("unit", "g");
JObject jsonObject = new JObject();
jsonObject.Add("name", "value0");
jsonObject.Add("amount", 19);
jsonObject.Add("unit", "ts");
//OPTION 1 to insert into the query command instead of recipe.Ingredients
JArray ingredientsJArray = new JArray();
ingredientsJArray.Add(jsonObject1);
ingredientsJArray.Add(jsonObject2);
ingredientsJArray.Add(jsonObject);
//AND OPTION 2 to insert into the query command instead of recipe.Ingredients
JObject[] ingredientsArray = new JObject[3];
ingredientsArray[0] = jsonObject;
ingredientsArray[1] = jsonObject1;
ingredientsArray[2] = jsonObject2;
For the Json handling I use Newtonsoft.Json (Nuget Package)
I also tried to make an array of (json formatted) strings to get the query working which understandably lead to exceptions which say that I use text[] instead of json[].
Is it really that hard to achieve this with c# npgsql? In other languages like js (npm package of pg) it is super easy. Or am I missing s.th. very obvious?
Remark: without the json[] column the query works like a charm.
Some help is highly appreciated. Thx!
PostgreSQL has an array type which is very different from a JSON array; in other words, you can't write a .NET JArray (which maps to PG json) to json[], which is your column. Instead, map a regular .NET array of JObject as follows:
var jsonObject1 = new JObject
{
{ "name", "value1" },
{ "amount", 1 },
{ "unit", "ml" }
};
var jsonObject2 = new JObject
{
{ "name", "value2" },
{ "amount", 2 },
{ "unit", "g" }
};
cmd.CommandText = "INSERT INTO Recipes (ingredients) VALUES (#p)";
cmd.Parameters.Add(new("p", NpgsqlDbType.Json | NpgsqlDbType.Array) { Value = new[] { jsonObject1, jsonObject2 } });
await cmd.ExecuteNonQueryAsync();
Note that you need to manually specify the NpgsqlDbType as in the above, opened this issue to make this better.
Finally, Npgsql also supports the built-in System.Text.Json as an alternative to Newtonsoft.Json - no additional plugin is needed for that.
I'm writing a program to read in CSV files and validate the data. The csv file is comma delimited.
The csv file contains a sales order that is retrieved online so we can't actually edit the CSV file itself. I need to read in the file and split it into the cells. However, the product description will contain further commas which is affecting how I access the data.
My code for pulling the values out is below.
private void csvParse()
{
List<string> products = new List<string>();
List<string> quantities = new List<string>();
List<string> price = new List<string>();
using (var reader = new StreamReader(txt_filePath.Text.ToString()))
{
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
products.Add(values[0]);
quantities.Add(values[2]);
values[3] = values[3].Substring(4);
price.Add(values[3]);
}
}
if (validateData(products, quantities, price) != "")
{
MessageBox.Show(validateData(products, quantities, price));
}
}
Is there anyway to ignore the columns in a set cell or can the columns distinguished by another delimiter?
A snippet of a row in my csv file is below.
The raw CSV data is below:
TO12345,"E45 Dermatological Moisturising Lotion, 500 ml",765,GBP 1.75
You can use LinqToCSV from nuGet. ie:
void Main()
{
List<MyData> sample = new List<MyData> {
new MyData {Id=1, Name="Hammer", Description="Everything looks like a nail to a hammer, doesn't it?"},
new MyData {Id=2, Name="C#", Description="A computer language."},
new MyData {Id=3, Name="Go", Description="Yet another language, from Google, cross compiles natively."},
new MyData {Id=3, Name="BlahBlah"},
};
string fileName = #"c:\temp\MyCSV.csv";
File.WriteAllText(fileName,"Id,My Product Name,Ignore1,Ignore2,Description\n");
File.AppendAllLines(fileName, sample.Select(s => $#"{s.Id},""{s.Name}"",""ignore this"",""skip this too"",""{s.Description}"""));
CsvContext cc = new CsvContext();
CsvFileDescription inputFileDescription = new CsvFileDescription
{
SeparatorChar = ',',
FirstLineHasColumnNames = true,
IgnoreUnknownColumns=true
};
IEnumerable<MyData> fromCSV = cc.Read<MyData>(fileName, inputFileDescription);
foreach (var d in fromCSV)
{
Console.WriteLine($#"ID:{d.Id},Name:""{d.Name}"",Description:""{d.Description}""");
}
}
public class MyData
{
[CsvColumn(FieldIndex = 1, Name="Id", CanBeNull = false)]
public int Id { get; set; }
[CsvColumn(FieldIndex = 2, Name="My Product Name",CanBeNull = false, OutputFormat = "C")]
public string Name { get; set; }
[CsvColumn(FieldIndex = 5, Name="Description",CanBeNull = true, OutputFormat = "C")]
public string Description { get; set; }
}
It should work..:)
var csvSplit = new Regex("(?:^|,)(\"(?:[^\"]+|\"\")*\"|[^,]*)", RegexOptions.Compiled);
string[] csvlines = File.ReadAllLines(txt_filePath.Text.ToString());
var query = csvlines.Select(csvline => new
{
data = csvSplit.Matches(csvline)
}).Select(t => t.data);
var row = query.Select(matchCollection =>
(from Match m in matchCollection select (m.Value.Contains(',')) ? m.Value.Replace(",", "") : m.Value)
.ToList()).ToList();
You can also use the Microsoft.VisualBasic.FileIO.TextFieldParser class. More detailed answer here: TextFieldParser
First of all my apologies because this is going to be a "How to" question rather than a technical question. I have a CSV file as follows-
London,Dubai,4
Dubai,Mumbai,8
Dubai,Dhaka,4
Now my plan is to create a JSON object from that CSV in the following format-
[
{
"From": "London",
"To": "Dubai",
"Duration": 4
},
{
"From": "Dubai",
"To": "Mumbai",
"Duration": 8
},
{
"From": "Dubai",
"To": "Dhaka",
"Duration": 4
},
]
How do I go about and do that? Currently I can load the CSV using OpenFileDialog but no idea what else I should do to get it done? Use Model Classes? JSON.Net? Please advice me and some code samples would be appreciated!
You can add csv records to a List<T> and then serialize it with Newtonsoft.Json to get your required JSON object. See the example below:
class Program
{
static void Main(string[] args)
{
string[] csv = new[] { "London,Dubai,4", "Dubai,Mumbai,8", "Dubai,Dhaka,4" };
List<model> list = new List<model>();
foreach (var item in csv)
{
string[] fields = item.Split(',');
list.Add(new model
{
From = fields[0],
To = fields[1],
Duration = fields[2]
});
}
var json = JsonConvert.SerializeObject(list);
Console.WriteLine(json);
Console.ReadLine();
}
}
public class model
{
public string From { get; set; }
public string To { get; set; }
public string Duration { get; set; }
}
You can use TextFieldParser from the Microsoft.VisualBasic.FileIO namespace and Microsoft.VisualBasic.dll assembly to parse CSV files. Despite the VisualBasic name the class is perfectly usable in c#.
First, add the following extension method:
public static class TextFieldParserExtensions
{
public static IEnumerable<string []> ReadAllFields(this TextFieldParser parser)
{
if (parser == null)
throw new ArgumentNullException();
while (!parser.EndOfData)
yield return parser.ReadFields();
}
}
Now you can use LINQ to transform each CSV line into an anonymous or named type for serialization, like so:
var csv = #"London,Dubai,4
Dubai,Mumbai,8
Dubai,Dhaka,4";
string json;
using (var stream = new StringReader(csv))
using (TextFieldParser parser = new TextFieldParser(stream))
{
parser.SetDelimiters(new string[] { "," });
var query = parser.ReadAllFields()
.Select(a => new { From = a[0], To = a[1], Duration = int.Parse(a[2]) });
json = new JavaScriptSerializer().Serialize(query);
}
Here I am using JavaScriptSerializer but the same code can be used with json.net
json = JsonConvert.SerializeObject(query, Formatting.Indented);
Be sure to evaluate the query before closing the TextFieldParser.
I Believe this should work for all different kinds of .csv files
Comments are in the code
public class Program
{
public static void Main(string[] args)
{
var list = new List<Dictionary<string, string>>();
Console.WriteLine("Put in the path to your .csv file");
var response1 = Console.ReadLine();
Console.WriteLine("Initializing...");
// Read All of the lines in the .csv file
var csvFile = File.ReadAllLines(response1);
// Get The First Row and Make Those You Field Names
var fieldNamesArray = csvFile.First().Split(',');
// Get The Amount Of Columns In The .csv
// Do the -1 so you can use it for the indexer below
var fieldNamesIndex = fieldNamesArray.Count() - 1;
// Skip The First Row And Create An IEnumerable Without The Field Names
var csvValues = csvFile.Skip(1);
// Iterate Through All Of The Records
foreach (var item in csvValues)
{
var newDiction = new Dictionary<string, string>();
for (int i = 0; i < fieldNamesIndex;)
{
foreach (var field in item.Split(','))
{
// Think Of It Like This
// Each Record Is Technically A List Of Dictionary<string, string>
// Because When You Split(',') you have a string[]
// Then you iterate through that string[]
// So there is your value but now you need the field name to show up
// That is where the Index will come into play demonstrated below
// The Index starting at 0 is why I did the -1 on the fieldNamesIndex variable above
// Because technically if you count the fields below its actually 6 elements
//
// 0,1,2,3,4,5 These Are The Field Names
// 0,1,2,3,4,5 These Are The Values
// 0,1,2,3,4,5
//
// So what this is doing is int i is starting at 0 for each record
// As long as i is less than fieldNamesIndex
// Then split the record so you have all of the values
// i is used to find the fieldName in the fieldNamesArray
// Add that to the Dictionary
// Then i is incremented by 1
// Add that Dictionary to the list once all of the values have been added to the dictionary
//
// Add the field name at the specified index and the field value
newDiction.Add(fieldNamesArray.ElementAt(i++), field);
}
list.Add(newDiction);
}
}
Console.WriteLine("Would You Like To Convert To Json Now?");
Console.WriteLine("[y] or [n]");
var response = Console.ReadLine();
if (response == "y")
{
Console.WriteLine("Where Do You Want The New File?");
var response2 = Console.ReadLine();
// Serialize the list into your Json
var json = JsonConvert.SerializeObject(list);
File.Create(response2).Dispose();
File.AppendAllText(response2, json);
Console.WriteLine(json);
Console.ReadLine();
}
else
{
Console.WriteLine("Ok See You Later");
Console.ReadLine();
}
}
}
Whenever i am trying to Serialize the Object with JsonConvert.SerializeObject it adds a default array name as "d"
json = JsonConvert.SerializeObject(new
{
resultsets = new List<Result>()
{
new Result { id = 1, value = "ABC", info = "ABC" },
new Result { id = 2, value = "JKL", info = "JKL" },
new Result { id = 3, value = "GSG", info = "DYU" }
}
});
return json;
The Json responce is
{
"d": "{"resultsets":[{"id":1,"value":"ABC","info":"ABC"},{"id":2,"value":"JKL","info":"JKL"},{"id":3,"value":"GSG","info":"DYU"}]}"
}
where extra array added with name "d"
i want simple array as follow
{"resultsets":[{"id":1,"value":"ABC","info":"ABC"},{"id":2,"value":"JKL","info":"JKL"},{"id":3,"value":"GSG","info":"DYU"}]}
This is to prevent direct script execution:
Suppose you were returning a plain array. The following is not a valid JS-statement:
{"d": [1]}
whereas this is:
[1]
You can find more information here:
http://encosia.com/a-breaking-change-between-versions-of-aspnet-ajax/#comment-34045
might seem really simple however I can't get my json to be correctly formatted from my MVC 5 controller.
My output is showing as;
[
{
"result":{
"account_color":"B43104",
"account_desc":"Welcome to XYZ",
"account_name":"XYZ",
"account_zone":1
}
},
{
"result":{
"account_color":"FF0000",
"account_desc":"Test Company",
"account_name":"Test",
"account_zone":2
}
}
]
So as you can see the level above result does not show any text so it seems like the 'result' section is getting added to a blank node
My controller is;
public IEnumerable<dynamic> Get()
{
return db.tblAccounts.Select(o => new
{
result = new
{
account_name = o.account_name,
account_desc = o.account_desc,
// account_image = Url.Content("~/images/") + String.Format("account_{0}.png", o.id),
account_color = o.account_color,
}
});
}
My json formatter is;
config.Formatters.Clear();
//config.Formatters.Add(new XmlMediaTypeFormatter());
var json = new JsonMediaTypeFormatter();
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.None;
config.Formatters.Add(json);
so it just appears that the 'result' is at a sub level it needs to be a level higher, any help would be great.
Try changing your code to look like this:
public IEnumerable<dynamic> Get()
{
return db.tblAccounts.Select(o =>
new
{
account_name = o.account_name,
account_desc = o.account_desc,
// account_image = Url.Content("~/images/") + String.Format("account_{0}.png", o.id),
account_color = o.account_color,
}
);
}
This will produce an array of results instead of the nested JSON that you provided. you don't actually need the result node label do you?
EDIT:
based on your response is this what you are looking for?
public dynamic Get()
{
var accountsNode = new {
accounts = db.tblAccounts.Select(o =>
new
{
account_name = o.account_name,
account_desc = o.account_desc,
// account_image = Url.Content("~/images/") + String.Format("account_{0}.png", o.id),
account_color = o.account_color,
}
).ToList()
};
return accountsNode;
}